Skip to content

Tenants live in a new tenants.yaml in panto-cloud-hq, not in registry.yaml


Tenants live in a new tenants.yaml in panto-cloud-hq, not in registry.yaml

Section titled “Tenants live in a new tenants.yaml in panto-cloud-hq, not in registry.yaml”

Date: 2026-08-18 Status: open Supersedes: none Superseded-by: none — current Upholds: MR-13

panto-cloud admits tenant ORGS. petrova-codes/registry.yaml admits REPOS. The question is whether they are the same object.

registry.schema.json describes itself as a list of repositories. slug must equal the workspace directory name; contract_sha is the 12-hex join key to state/.yaml; url is a git remote; fleets_allowed[], profile, contract_committers[] and integrations_applicability over ares|traceo|crumb|rocky|eva are all repo-scoped. For a tenant org at least six of twelve fields are meaningless.

The genuine counter-argument, which must be stated before it is dismissed: registry.schema.json ALREADY represents org-level, App-installed, repo-less entities. Line 44 makes url optional and line 53 defines role: placeholder as ‘an org has the Petrova-act App installed but no governance repo yet’, rendering as not_onboarded on /console/phases. That is an org record wearing a repo schema, and it is the strongest reason to reuse.

Create tenants.yaml and tenants.schema.json in panto-cloud-hq. Do not extend registry.yaml.

The counter-argument loses at 20-100 tenants for five reasons:

  1. Scale swamps the host. registry.yaml holds 38 human-reviewed rows with multi-paragraph notes. Adding 100 near-empty rows makes the file majority-noise and degrades the human review that is its entire purpose.
  2. Different admission semantics. Admitting a repo grants WRITE verbs gated by profile and fleets_allowed. Admitting a tenant org grants READ on a third party’s property. Same file, two meanings of admitted, one refusal code — that is how a misconfiguration becomes an incident.
  3. Different blast radius, therefore different repo. A bad registry.yaml merge misgoverns the operator’s own repos; a bad tenants.yaml merge reads someone else’s. These must not share a review queue.
  4. Different committers. registry.yaml is human-PR-only. tenants.yaml is PROPOSED by the broker webhook on installation.created and merged by a human — a mixed path registry.yaml deliberately lacks.
  5. Cross-org coupling. registry.yaml lives in petrova-codes; putting tenants there would make panto-core’s broker depend on a different GitHub org’s repo at request time.

Schema mirrors registry.schema.json’s discipline deliberately: additionalProperties false, version as a const integer, shard with default global, absolute dates, notes free text.

Editing: humans merging PRs in panto-cloud-hq only. The broker may OPEN PRs and may never merge. Auto-demotion (active -> suspended on installation.deleted) is enforced at token-mint time regardless of file state, so a demotion never waits on a merge; the PR follows for the record. Promotion always requires the merge — App installation is necessary and not sufficient, the same asymmetry as probes never auto-promoting.

Follow-up, not decided here: whether existing role: placeholder rows in registry.yaml migrate to tenants.yaml or survive alongside. That is a decision, not a refactor.

Reuse registry.yaml with tenant orgs as additional rows

Section titled “Reuse registry.yaml with tenant orgs as additional rows”

Rejected: Repo-shaped schema leaves six of twelve fields meaningless for an org; 100 added rows would swamp a 38-row human-reviewed file; and it would deepen the role: placeholder seam by making one refusal code cover both write-verb admission and third-party read admission.

tenants.yaml inside panto-core or panto-state

Section titled “tenants.yaml inside panto-core or panto-state”

Rejected: The runtime would govern its own admission — the component that harvests tenants deciding which tenants exist. panto-cloud-hq is governance-only with no runtime, which keeps the separation.

A database or Vercel Edge Config so the broker reads without a git fetch

Section titled “A database or Vercel Edge Config so the broker reads without a git fetch”

Rejected: Puts admission outside PR review and breaks the machine-surface-bound-to-sources property. The broker can read a build-time-baked copy exactly as scripts/vercel-build.sh already stages registry.yaml and state/ into _render.func for /api/rpc to read at runtime.

  • registry.schema.json
  • registry.yaml
  • cli/src/registry.ts:88-93
  • scripts/vercel-build.sh
  • docs/decisions/2026-05-10-rpc-into-astro.md

Human merge required — this PR is opened with the awaiting-human-merge label and does not auto-merge.