carlos / platform Public

member-stated TCP upstreams: decide the trust policy for addrs on the console door Idea open

On branch tenant-iso-routes

Migrated from github.com/carlosframework/platform issue #170, opened 2026-08-12. GitHub issues are closed for this repo; see AGENTS.md, "Work is tracked on amadan, not GitHub".

Still outstanding: The trust policy for member-stated TCP upstreams is still undecided: manifest opt-in, tenant isolation, box-local port denial.

---

Surfaced by the #152 build's task review (branch multi-upstream-routes, console PATCH/POST for addrs). Before this feature, no member-facing door could state a TCP upstream; now POST/PATCH instances let an app member point their TLS-fronted hostname at any host:port the box can dial. validAddr is syntax-only.

The branch ships a deliberately minimal rail — 169.254.0.0/16 (link-local/metadata) refused; loopback and RFC1918 allowed because existing operator-created addr routes legitimately use both. The open policy questions are Paul's:

  • Should member-stated upstreams need a manifest opt-in (the instances-manifest door is the natural place)?
  • Tenant isolation: on a shared box, member A can point at member B's TCP service today. Real for the Rails PoC boxes? For Carloku multi-tenant, certainly.
  • Should box-local ports (console, registry-adjacent services) be denied for MEMBER-created records while staying legal for operator/store-mode writes?

Blocking question for making #152's door live on a multi-tenant console; not blocking the branch merge itself if the door ships dark or operator-only first.

🤖 Generated with Claude Code

Reposting a ruling that was lost when GitHub #170 moved here. Paul's comment from https://github.com/carlosframework/platform/issues/170#issuecomment-5430765122 (2026-08-26), verbatim:

> Ruling (Paul, 2026-08-26): member-stated upstreams are admitted only when every address is inside the member's own declared fleet (the fleet's box addresses the registry already knows); box-local ports stay denied for member writes; a manifest opt-in gates whether an app accepts member-stated upstreams at all. Operator/store-mode writes keep today's rail (link-local refused, loopback/RFC1918 allowed). Not yet built.

Status, 2026-10-04: branch tenant-iso-routes (#214 item 4) builds part of it. Member writes are refused for loopback, private, CGNAT and other non-public addresses and for hostnames, and operator writes keep the old rule. It still lets members use any public IP, which is wider than "only inside the member's own fleet". The fleet allowance and the manifest opt-in are not built.

Decision (Paul, 2026-10-06): until the own-fleet allowance is built, members can't state upstream addresses at all, so instances create with addrs is operator-only. A member PATCH may keep or remove addresses already on the record, and existing routes and operator writes are unchanged. Paul's condition is that this doesn't affect what existing tenants are doing. No code in the Tito repos sets addrs or set-upstreams. Being built on tenant-iso-routes. This keeps the 2026-08-26 ruling; the fleet allowance and the manifest opt-in stay open here.

Merged to main as 1c43c2c. Members can't add upstreams; existing ones can be kept, reordered or dropped; operators keep today's rule. One check before v0.25.0 is cut: confirm in the flagship and Tito console audit logs that no app or service token adds upstreams today, because they would now get 403. No caller exists in any local repo. Still open here: the own-fleet allowance and the manifest opt-in.

Tracked under #247 (tenant isolation before Carloku takes outside tenants).

Audit check (2026-10-07, read-only scan of the flagship bucket): 153 instance records, 7 with stated upstreams. All 7 are platform-run apps on loopback: keymail-push (bae) and woodstar-apbridge, -indexer, -media, -notify, -relay and -unfurl (bdm). They were written by the operator, and no app's repo sets upstreams through a token. Existing records keep serving unchanged, so the operator-only rule affects no tenant.