Prompt: take an ird p2p app from dev to production
Have an agent harden an existing ird p2p app for launch: tight origins,
a branded wildcard hostname on your own zone, mailbox tokens minted only
by your backend, limits sized to the rooms and peers you expect,
monitoring hooks, a cost model from the relay rates, and a written
rollback — each change snapshotted first and applied only on your yes.
Needs: ird access (MCP server or the ird CLI, logged in); an existing p2p app; for the custom domain, a zone hosted on ird DNS
Costs: the app's existing hourly rate and per MB relayed / per MiB-hour cached (credits_prices → recurring.p2p-app-hourly); each backend token mint bills p2p.credentials; origin, domain and limit changes have no price-book entry
Group: p2p
Paste everything below the line into a fresh conversation. Fill in the
FILL IN block first.
Task
Bring the app below to production configuration, with a before/after
diff per change, applied only after I confirm. Nothing is
deleted or disabled.
FILL IN
APP: notes # existing p2p app (name, hostname or id)
PROD_ORIGINS: https://notes.example.ro, *.notes.example.ro # only these; bare wildcards
DOMAIN: rtc.example.ro # hostname on an ird-DNS zone, or blank
WILDCARD: yes # also serve *.DOMAIN (zone must be on ird DNS)
ROOMS: 200 # expected concurrent rooms
PEERS_ROOM: 8 # expected peers per room
SESSIONS_MO: 20000 # sessions per month
MB_SESSION: 30 # average MB per session
TURN_SHARE: 0.15 # share of sessions falling back to TURN/relay (assumption, replace with measured)
CLOSED_MINT: yes # mailbox tokens only from my backend (if the mailbox is on)
Non-negotiable rules
- Snapshot before every change. Save the full
p2p_list_apps
entry (CLI: ird p2p info APP --json) — origins, settings,
domains, mailbox flags — as the rollback baseline. Show the diff,
wait for a yes, apply, re-read.
- Origins replace whole.
p2p_set_origins overwrites the list;
send it complete. Wildcards are bare (*.example.ro);
https://*.example.ro is rejected. Never empty in production.
- Never disable the mailbox or delete the app. Disabling drops
stored messages; deleting stops the hostnames immediately.
- Rates from
credits_prices, usage from p2p_usage. No numbers
from memory.
Steps
A. Baseline. p2p_list_apps → the APP entry; p2p_usage (CLI:
ird p2p usage) → relayed bytes this period, relay_bytes_total,
mailbox_bytes_total, cached_bytes, hourly/monthly. GET
https://<host>/.well-known/ap2p → the live limits.
B. Origins. Diff current vs PROD_ORIGINS; drop localhost and
staging. p2p_set_origins(app=APP, origins=[PROD_ORIGINS])
(CLI: ird p2p origins APP --set a,b) gates the WebSocket upgrade,
/turn-credentials, the relay upgrade and the mailbox open mint; live
within a minute. Verify: curl -H "Origin: https://evil.example.com"
https://<host>/turn-credentials is refused, a PROD origin is not.
C. Custom domain. If DOMAIN: its zone must be in dns_list_zones.
p2p_domain_add(app=APP, hostname=DOMAIN, wildcard=WILDCARD) (CLI:
ird p2p domains add APP DOMAIN --wildcard). On an ird-hosted zone
records and certificate are automatic — a wildcard needs this.
Otherwise set the returned dns_cname_target as a CNAME and run
p2p_domain_verify(app=APP, domain=DOMAIN). The descriptor is
host-aware: fetched from DOMAIN it advertises DOMAIN's multiaddrs.
Switch the client to DOMAIN and repeat the two-browser test.
D. Closed-mint mailbox. Only if mailbox_enabled and CLOSED_MINT:
p2p_set_mailbox(app=APP, open_mint=false) (CLI: ird p2p mailbox APP
--closed-mint); omit enabled. The browser mint then refuses; my
backend mints with p2p_mailbox_credentials(app=APP, room=<room or
omit>, ttl_sec=…) (CLI: ird p2p mailbox creds APP --room …; API:
POST /p2p/apps/:id/mailbox-credentials) and hands the token to the
client in its invite flow. Tokens verify offline — no revocation — so
keep ttl_sec short and room-scoped. Each mint bills p2p.credentials.
E. Limits. Defaults (from p2p_set_limits): signaling max_rooms
500, max_room_peers 16, max_conns_per_ip 20, max_bytes_per_sec
256 KiB/s; relay max_relay_reservations 128, max_relay_circuits 64,
relay_circuit_duration_sec 3600, relay_circuit_data_mb 512,
max_relay_bytes_per_sec 256 KiB/s, max_relay_conns_per_ip 20;
mailbox mailbox_ttl_hours 24, mailbox_max_mb 256,
mailbox_max_message_kb 64, mailbox_mint_ip_per_min 10,
mailbox_mint_app_per_min 600. Size (×1.5 = headroom, an assumption):
max_rooms ≥ ROOMS × 1.5 (one pool shared by /ws, y-webrtc topics,
tracker swarms and PeerJS clients), max_room_peers ≥ PEERS_ROOM ×
1.5, max_conns_per_ip up for users behind one office NAT; libp2p:
reservations ≥ concurrent browser peers. Only passed keys change, 0
resets, values are clamped; more relay throughput means more can bill.
p2p_set_limits(app=APP, …) (CLI: ird p2p limits APP --set k=v).
Re-read the descriptor.
F. Monitoring. Weekly p2p_usage (relayed bytes and cached_bytes
vs the model in G); client logging of signaling error codes
too-many-rooms, room-full, rate-limited and relay/mint HTTP 429;
a boot-time descriptor fetch so limits and relay ids are never
hardcoded.
G. Cost model. Monthly ≈ per_hour × 730 + SESSIONS_MO ×
MB_SESSION × TURN_SHARE × per_mb_relayed + average cached MiB × 730 ×
per_mb_hour_cached + mints × p2p.credentials. Direct WebRTC bytes
cost nothing. After a week, replace TURN_SHARE with the measured share.
H. Rollback. Per change: origins → p2p_set_origins with the saved
list; domain → p2p_domain_delete(app=APP, domain=DOMAIN), client
back to <name>.ap2p.ro; mint → p2p_set_mailbox(app=APP,
open_mint=true); limits → p2p_set_limits with the saved values (or
0 per key). No price-book entry; origins and limits apply within a minute.
Deliverable
The before/after table (origins, domains, mailbox mint, changed
limits), verification output for B, C and E, the cost model, the
monitoring checklist, and the rollback commands beside the saved
baseline.