Tenant/Repo/App Surface Implementation Plan

Tenant/Repo/App Surface Implementation Plan

Goal

Implement the new domain direction:

This plan is optimized for current reality: pre-production and one active user.

What changes

  1. Current App becomes a repository concept in practice.
  2. Add first-class Tenant.
  3. Add first-class App Surface under each repository.
  4. Keep existing /api/apps working (backward-compatible) while adding clearer /api/repos and /api/tenants APIs.
  5. Runtime profiles gain surface endpoint mapping.

What stays the same

Implementation order (critical path)

Step 1: Domain + storage model

Crates/files:

Tasks:

  1. Add domain structs:
    • Tenant { id, name, slug, created_at, updated_at }
    • AppSurface { id, repo_id, key, title, domains, branding?, roles?, created_at, updated_at }
  2. Extend existing app/repo model with tenant_id.
  3. Add Mongo collections/indexes:
    • tenants.slug unique
    • app_surfaces (repo_id, key) unique
    • apps.tenant_id non-unique index
  4. One-time local backfill:
    • create a default tenant
    • assign all existing repos to it

Done when:

Step 2: API surface (tenant + repo + app-surface)

Crates/files:

Tasks:

  1. Add tenant endpoints:
    • POST /api/tenants
    • GET /api/tenants
    • GET /api/tenants/:tenantId
  2. Add repo endpoints:
    • POST /api/tenants/:tenantId/repos
    • GET /api/repos
    • GET /api/repos/:repoId
  3. Keep /api/apps endpoints functional as compatibility alias.
  4. Add app-surface endpoints:
    • POST /api/repos/:repoId/surfaces
    • GET /api/repos/:repoId/surfaces
    • PATCH /api/repos/:repoId/surfaces/:surfaceId

Done when:

Step 3: Runtime profile multi-surface support

Crates/files:

Tasks:

  1. Add surface_endpoints to runtime profile:
    • shape: HashMap<String, String> (surface_key -> base_url)
  2. Validate keys:
    • must match existing repo surface keys
  3. Keep existing single-url fields as compatibility path (if present).
  4. Update temp env derivation logic so endpoint overrides can be per-surface.

Done when:

Step 4: Changeset/release visibility for surfaces

Crates/files:

Tasks:

  1. Add impacted_surface_keys: Vec<String> to changeset metadata.
  2. Populate it from:
    • changed file paths (first pass)
    • optional semantic diff enrichment (second pass)
  3. Propagate impact summary into release detail responses.

Done when:

Step 5: Auth and membership alignment

Keep it simple for now:

Tasks:

  1. Ensure new tenant/repo/surface endpoints enforce current RBAC correctly.
  2. Ensure invite/member flows still work with repo IDs unchanged.

Done when:

Step 6: Test and docs pass

Tasks:

  1. Add/adjust unit and integration tests:
    • tenant/surface repos
    • new handlers
    • runtime profile endpoint map validation
  2. Update manual test guide with new setup sequence:
    • create tenant -> create repo -> create surfaces
  3. Keep OpenAPI docs aligned with the new endpoints.

Done when:

Practical execution checklist

  1. Implement Step 1 and Step 2 first (unblocks everything else).
  2. Then Step 3 (runtime profiles).
  3. Then Step 4 (impacted surface metadata).
  4. Finish with Step 5 and Step 6 hardening.

Notes for this repo right now

Automated acceptance criteria

When implementation is complete, these checks must pass.

ID Criteria Automated check
TRS-AC-01 Tenant can be created and queried. run_tenant_repo_surface_acceptance.sh
TRS-AC-02 Repository can be created under a tenant and queried via /api/repos/:id. run_tenant_repo_surface_acceptance.sh
TRS-AC-03 /api/apps/:id compatibility still works for repo records. run_tenant_repo_surface_acceptance.sh
TRS-AC-04 Two app surfaces can be created and listed for one repo. run_tenant_repo_surface_acceptance.sh
TRS-AC-05 Runtime profile stores and returns surface_endpoints. run_tenant_repo_surface_acceptance.sh
TRS-AC-06 Environment configuration can reference runtime profiles after model change. run_tenant_repo_surface_acceptance.sh
TRS-AC-07 Existing lifecycle smoke remains functional after model change. tests/e2e/run_full_staged_smoke.sh

Acceptance command set

  1. CONMAN_BASE_URL=... CONMAN_LOGIN_EMAIL=... CONMAN_LOGIN_PASSWORD=... CONMAN_ACCEPTANCE_REPO_PATH=... ./tests/ops/run_tenant_repo_surface_acceptance.sh --strict
  2. ./tests/e2e/run_full_staged_smoke.sh

The first command validates the new model contracts. The second command guards against regressions in the current app/workspace/changeset/release/deploy flow.