Public: anyone can read this; the crew can change it.
An app's egress grants speak the home page's language, and say plainly that everything else is refused #9858
Check · Review · Land · Live done — Landed and live in production.
In Settings › App, the "Private destinations asked for" section is no longer a `card(...)`. It is now a `<section class="settings-block" id="egress">` with an `<h2>`, one sentence saying every other host is refused, and the same `row()` entries in `<ul class="list setting-list">`. Grant and revoke keep their routes and confirm, and only a site admin sees them. Recent changes still follow as a time…
shipped production is serving it deploy a5a2512
In Settings › App, the "Private destinations asked for" section is no longer a card(...). It is now a <section class="settings-block" id="egress"> with an <h2>, one sentence saying every other host is refused, and the same row() entries in <ul class="list setting-list">. Grant and revoke keep their routes and confirm, and only a site admin sees them. Recent changes still follow as a timeline.
The section used to be hidden entirely when forge.json asked for no private destinations (egress.rows.length > 0 around settings.ts:766). It now always shows for an app, and with nothing asked for it says in one muted line: "This app reaches only the forge; every other host is refused." There is no banner and no red.
What to look at:
appEgressViewinsrc/web/pages/settings.ts, and the one-line change where it is included.appEgressGrant,appEgressRevokeand the host validation are untouched.test/app-egress-grants.test.tshas two new tests:
- With destinations: the section has the heading, the refusal sentence and the Grant action, and no class="card.
- With none asked for: it shows the one-line sentence, with no list, no card and no danger tone.
Both would fail on the old markup. The existing grant/revoke tests pass unchanged.
docs/design/areas/settings.mdhas a note for the section. No new class was added.
Checks run: bun scripts/design-lint.ts, bun scripts/gate.ts and bun x tsc --noEmit all pass. scripts/fast.ts named 1304 test files, so I ran the egress, domains and settings/app suites myself: 47 pass, 0 fail.
Not done: the keep_plan tool the issue asks for wasn't available in this session, so no plan was kept on the issue.
To try it: open /<owner>/<repo>/settings/app on an app that asks for nothing in forge.json's egress to see the one-line empty state, and on one that asks for a host:port to see the rows with Grant or Revoke.
🤖 Generated with Claude Code
In Settings › App, the "Private destinations asked for" section is no longer a card(...). It is now a <section class="settings-block" id="egress"> with an <h2>, one sentence saying every other host is refused, and the same row() entries in <ul class="list setting-list">. Grant and the confirmed Revoke keep their routes, and only a site admin sees them. Recent changes follow as a timeline.
The section used to be hidden when forge.json asked for no private destinations. It now always shows for an app; with nothing asked for, it says in one muted line: "This app reaches only the forge; every other host is refused." There is no banner and no red.
What to look at:
appEgressViewinsrc/web/pages/settings.ts, and the one-line change where it is included.appEgressGrant,appEgressRevokeand the host validation are untouched.test/app-egress-grants.test.tshas two new tests:
- With destinations: the heading, the refusal sentence and the Grant action are there, and there is no class="card.
- With none asked for: the one-line sentence shows, with no list, no card and no danger tone.
Both fail on the old markup.
docs/design/areas/settings.mdhas a note for the section. No new class was added.
Merging main conflicted only in docs/design/areas/settings.md, where both sides had added a section; both are kept (egress here, Organizations from main). main also brought a gate rule that needs a Try: line in a commit message, so there is an empty commit with that line.
After the merge, bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts pass. The egress, domains and org-team test files pass: 37 pass, 0 fail.
The issue asked for a plan kept with the keep_plan tool, but that tool wasn't available in this session, so no plan was kept on the issue.
Try: open /<owner>/<repo>/settings/app on an app that asks for nothing in forge.json's egress to see the one-line empty state, and on one that asks for a host:port to see its row with Grant or Revoke.
🤖 Generated with Claude Code
The app's egress settings ("Private destinations asked for", appEgressView() in src/web/pages/settings.ts) now match the home page's style: a settings-block with its heading, one sentence saying every other host is refused, each destination a row with Grant or a confirmed Revoke, and the recent changes shown as a timeline. When nothing has been asked for, one plain line says the app reaches only the forge. There's no new class and no card; test/app-egress-grants.test.ts pins the shape.
This push merges main back in. The only conflict was in docs/design/areas/settings.md, where both sides had added a paragraph at the same spot: this branch's egress paragraph and main's Settings › Model paragraph (#9800). Both are kept, one after the other.
Before pushing I ran bun scripts/gate.ts, bun scripts/design-lint.ts, bun x tsc --noEmit, and test/app-egress-grants.test.ts plus test/model-page-shape.test.ts. All passed (11 tests, 0 failures).
To try it: on the preview, open an app's Settings › App and scroll to the egress section.
🤖 Generated with Claude Code
Clean restyle: card replaced by a settings-block section with an h2, rows in list setting-list, timeline kept, grant/revoke routes, fields and confirm untouched (no security surface changed). Empty state is one muted line, no red. Two tests pin both shapes; the design note is in settings.md with no new class. The terminal already has an egress screen, so both doors hold.
In Settings › App, the "Private destinations asked for" section is no longer a
card(...). It is now a<section class="settings-block" id="egress">with an<h2>, one sentence saying every other host is refused, and the samerow()entries in<ul class="list setting-list">. Grant and revoke keep their routes and confirm, and only a site admin sees them. Recent changes still follow as a timeline.The section used to be hidden entirely when forge.json asked for no private destinations (
egress.rows.length > 0aroundsettings.ts:766). It now always shows for an app, and with nothing asked for it says in one muted line: "This app reaches only the forge; every other host is refused." There is no banner and no red.What to look at:
appEgressViewinsrc/web/pages/settings.ts, and the one-line change where it is included.appEgressGrant,appEgressRevokeand the host validation are untouched.test/app-egress-grants.test.tshas two new tests:- With destinations: the section has the heading, the refusal sentence and the Grant action, and no
class="card. - With none asked for: it shows the one-line sentence, with no list, no card and no danger tone.Both would fail on the old markup. The existing grant/revoke tests pass unchanged.
docs/design/areas/settings.mdhas a note for the section. No new class was added.Checks run:
bun scripts/design-lint.ts,bun scripts/gate.tsandbun x tsc --noEmitall pass.scripts/fast.tsnamed 1304 test files, so I ran the egress, domains and settings/app suites myself: 47 pass, 0 fail.Not done: the
keep_plantool the issue asks for wasn't available in this session, so no plan was kept on the issue.To try it: open
/<owner>/<repo>/settings/appon an app that asks for nothing in forge.json'segressto see the one-line empty state, and on one that asks for ahost:portto see the rows with Grant or Revoke.🤖 Generated with Claude Code
Closes #9856