Team/Repo/App Implementation Plan
Team/Repo/App Implementation Plan
Goal
Implement the new domain direction:
Team -> Config Repository -> App- Keep Git lifecycle repo-scoped
(
workspace -> changeset -> release -> deploy) - Add multi-surface support for URLs/runtime profile context
This plan is optimized for current reality: pre-production and one active user.
What changes
- Current
Appbecomes a repository concept in practice. - Add first-class
Team. - Add first-class
Appunder each repository. - Keep
/api/reposand/api/teamsas the canonical API surfaces. - Runtime profiles gain surface endpoint mapping.
What stays the same
- Queue-first changesets/releases model.
- One integration branch per repository.
- Environment pipeline and deploy flow.
- gitaly-rs integration boundary.
Implementation order (critical path)
Step 1: Domain + storage model
Crates/files:
conman-core: addteam.rs,app_surface.rs; keepapp.rsas repo model.conman-db: addteam_repo.rs,app_surface_repo.rs.conman-db/src/lib.rs: export new repos and include index bootstrap.
Tasks:
- Add domain structs:
Team { id, name, slug, created_at, updated_at }AppSurface { id, repo_id, key, title, domains, branding?, roles?, created_at, updated_at }
- Extend existing app/repo model with
team_id. - Add Mongo collections/indexes:
teams.sluguniqueapp_surfaces (repo_id, key)uniqueapps.team_idnon-unique index Done when:
- service boots with new collections/indexes
Step 2: API surface (team + repo + app)
Crates/files:
conman-api/src/handlers/teams.rs(new)conman-api/src/handlers/apps.rs(repository handlers)conman-api/src/handlers/app_surfaces.rs(new)- router wiring in
conman-api
Tasks:
- Add team endpoints:
POST /api/teamsGET /api/teamsGET /api/teams/:teamId
- Add repo endpoints:
POST /api/teams/:teamId/reposGET /api/reposGET /api/repos/:repoId
- Add app endpoints:
POST /api/repos/:repoId/appsGET /api/repos/:repoId/appsPATCH /api/repos/:repoId/apps/:surfaceId
Done when:
- team/repo/surface can be created and listed end-to-end
Step 3: Runtime profile multi-surface support
Crates/files:
conman-core/src/runtime_profile.rsconman-db/src/runtime_profile_repo.rs- profile handlers under
conman-api
Tasks:
- Add
surface_endpointsto runtime profile:- shape:
HashMap<String, String>(surface_key -> base_url)
- shape:
- Validate keys:
- must match existing repo surface keys
- Update temp env derivation logic so endpoint overrides can be per-surface.
Done when:
- environment profile can define endpoints for multiple apps
- temp env creation keeps endpoint map and applies overrides correctly
Step 4: Changeset/release visibility for surfaces
Crates/files:
conman-core/src/changeset.rsconman-core/src/release.rsconman-apichangeset/release handlers
Tasks:
- Add
impacted_surface_keys: Vec<String>to changeset metadata. - Populate it from:
- changed file paths (first pass)
- optional semantic diff enrichment (second pass)
- Propagate impact summary into release detail responses.
Done when:
- review and release screens can show which surfaces are affected
Step 5: Auth and membership alignment
Keep it simple for now:
- Membership remains repo-scoped (current behavior).
adminremains the admin capability role.- Team-level admin model can be deferred.
Tasks:
- Ensure new team/repo/surface endpoints enforce current RBAC correctly.
- Ensure invite/member flows still work with repo IDs unchanged.
Done when:
- no regression in login/invite/member assignment
Step 6: Test and docs pass
Tasks:
- Add/adjust unit and integration tests:
- team/surface repos
- new handlers
- runtime profile endpoint map validation
- Update manual test guide with new setup sequence:
- create team -> create repo -> create surfaces
- Keep OpenAPI docs aligned with the new endpoints.
Done when:
cargo test --workspacepasses- manual API sequence works cleanly with team/repo/surface model
Practical execution checklist
- Implement Step 1 and Step 2 first (unblocks everything else).
- Then Step 3 (runtime profiles).
- Then Step 4 (impacted surface metadata).
- Finish with Step 5 and Step 6 hardening.
Notes for this repo right now
- Existing code already treats
Applike a repo (repo_path,integration_branch), so this change is mostly additive + naming clarity.
Automated acceptance criteria
When implementation is complete, these checks must pass.
| ID | Criteria | Automated check |
|---|---|---|
| TRS-AC-01 | Team can be created and queried. | run_team_repo_surface_acceptance.sh |
| TRS-AC-02 | Repository can be created under a team and queried via
/api/repos/:id. |
run_team_repo_surface_acceptance.sh |
| TRS-AC-03 | Two apps can be created and listed for one repo. | run_team_repo_surface_acceptance.sh |
| TRS-AC-04 | Runtime profile stores and returns
surface_endpoints. |
run_team_repo_surface_acceptance.sh |
| TRS-AC-05 | Environment configuration can reference runtime profiles after model change. | run_team_repo_surface_acceptance.sh |
| TRS-AC-06 | Existing lifecycle smoke remains functional after model change. | tests/e2e/run_full_staged_smoke.sh |
Acceptance command set
CONMAN_BASE_URL=... CONMAN_LOGIN_EMAIL=... CONMAN_LOGIN_PASSWORD=... CONMAN_ACCEPTANCE_REPO_PATH=... ./tests/ops/run_team_repo_surface_acceptance.sh --strict./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.