PayCargo · AI-Sandbox · Process

6.dRepo structure + app submission flow

Monorepo with three top-level folders (substrate / console / cartridges), department-segmented cartridges, CODEOWNERS-based ownership boundaries, per-layer CI workflows. The shape that makes vibe-scripter contribution safe by construction and makes the Phase D three-repo split mechanical when its time comes.
Block: 6.d (Console doctrine extension) · State: Specced, executes during Phase A restructure · Pins: §22 (cartridges segment by owning department)
Specced — landing this week

The restructure happens before chatbot code lands. This doc captures the structure, the access boundaries, and the criteria for the eventual three-repo split.

1. The structure

paycargo-ai-platform/ ├── README.md ├── CLAUDE.md / MODULES.md ├── _process/ # build doctrine + deployment record (local; gitignored) ├── _docs/ # strategy / business context │ ├── substrate/ # platform infrastructure (Steps 0-5) │ ├── bootstrap/ # state backend + OIDC + permission boundary │ ├── modules/platform/ # KMS, network, data, observability, schedules, etc. │ └── environments/ai-sandbox/ # composition + tfvars │ ├── console/ # the launcher + shared SDK │ ├── auth.tf, backend.tf, frontend.tf # Console app TF │ ├── frontend/ # launcher HTML/JS │ ├── lambda/ # launcher backend │ ├── cloudfront/ # CF Functions (SPA router) │ ├── sdk/v1/ # versioned SDK every cartridge loads │ │ ├── css/{tokens,components}.css │ │ └── js/{cartridge-auth,table,pagination,modal}.js │ ├── _platform/ # substrate-level Lambdas (App Registry endpoint, etc.) │ └── README.md │ ├── cartridges/ # vibe apps, department-segmented │ ├── _template/ # scaffold for new vibe apps │ ├── global/ # cross-cutting platform tools │ │ └── chatbot/ # first native cartridge (Step.6.j) │ ├── administrative/ # platform admin + ops tooling │ │ └── obs/ # observability app (operator surface) │ ├── engineering/ # eng-vibe-scripter productivity tools │ │ └── code-agents/ # golden-spec + future agents (Step.6.l) │ ├── sales/, marketing/, hr/, # empty until each lands its first cartridge │ ├── finance/, labs/ │ └── README.md │ ├── .github/ │ ├── workflows/ │ │ ├── terraform-plan.yml # one plan job today; split per layer if needed │ │ └── terraform-apply.yml # workflow_dispatch + confirm=APPLY guard │ └── CODEOWNERS # write-access boundaries per §22 └── .gitignore

Three top-level folders. One CI lane today (split per layer when scale demands). Ownership cohorts via CODEOWNERS — every folder routes to its owning team. The boundaries map to who's allowed to write what.

Why administrative/ instead of engineering/ for the obs app: the obs app watches the platform on behalf of every operator. It's admin/ops tooling, not engineering-specific. engineering/ stays as a placeholder for actual engineering-vibe-scripter cartridges. Why chatbot is under global/: the chatbot is cross-cutting — every department will use it. Apps that genuinely belong to one department go under that department's folder; cross-cutting apps live under global/ with their consumption gated at the Cognito-group level (the Cartridges tab's "Access" config controls this declaratively).

2. CODEOWNERS — the access boundary

# Substrate — platform team only
/substrate/                       @platform-team

# Console — engineering owns functional; UI team owns visual
/console/sdk/v1/css/              @ui-team
/console/sdk/v1/components.css    @ui-team
/console/sdk/v1/design-tokens.css @ui-team
/console/sdk/v1/                  @engineering-team
/console/_platform/               @engineering-team

# Cartridges — department-scoped vibe scripters
/cartridges/global/               @platform-team
/cartridges/administrative/       @admin-ops-team
/cartridges/engineering/          @engineering-vibe-scripters
/cartridges/sales/                @sales-vibe-scripters
/cartridges/marketing/            @marketing-vibe-scripters
/cartridges/hr/                   @hr-vibe-scripters
/cartridges/finance/              @finance-vibe-scripters
/cartridges/labs/                 @engineering-team  # lower review bar; loose oversight

# Catch-all
*                                 @platform-team

For Phase A (single human in all roles), every line is one person. The structure is right from day one. When external contributors arrive, role groups expand to include them without restructuring.

3. App submission flow

  1. Vibe scripter branches off main: cartridge/<app-name>
  2. Scaffold from template: cp -r cartridges/_template cartridges/<department>/<app-name>
  3. Vibe scripter writes business logic in 50-line route handlers; consumes SDK exclusively
  4. PR opens against main
  5. CI runs in parallel:
    • cartridge-plan.yml — Terraform plan against the substrate's state
    • SDK contract validator — confirms no raw AWS SDK imports in app code; PII-tag check; class-name CSS lint
    • App Review PR template auto-triggers — populates the "what changed" sections
  6. Reviewer cohorts activate via CODEOWNERS:
    • platform-team — if substrate touched
    • engineering-team — if SDK additions proposed
    • ui-team — if CSS or design tokens touched
    • peer vibe scripters in the same department — for business logic
  7. PR merges after required approvals
  8. Operator dispatches cartridge-apply.yml with confirm = APPLY
  9. Apply writes a row into ai-sandbox-app-registry DDB (immutable; append-only per §22)
  10. App appears in the platform's AppMenu for users with the right Cognito groups

4. Cross-layer dependency rules

FromToAllowed?Mechanism
cartridges/*console/sdk/v1/YesImports / link from app's HTML; Terraform consumes SDK module outputs
cartridges/*substrate/No (direct)All substrate access goes through SDK helpers; cartridges read substrate's output values via remote-state data sources only when the SDK doesn't suffice (rare)
console/sdk/substrate/YesSDK Terraform modules consume substrate outputs (CMK ARNs, role ARNs, etc.) via remote-state data sources
console/_platform/substrate/YesSame as SDK
substrate/console/ or cartridges/No (one-way)Substrate must not depend on anything above it in the stack

5. Phase D split criteria — when monorepo becomes three repos

Stay monorepo until at least one of these is true:

The monorepo's folder structure mirrors what the three-repo split would be. Migration is git filter-branch + tfstate migration + CI workflow split. ~1 day of platform-team work.

6. Department segmentation aligns with the data governance grid

The cartridge folders mirror the same departmental axis the data governance grid (Step 4.5.a) uses for CMKs:

Cartridge folderNative governance cells (Phase 1)Future cells
cartridges/global/uses platform's chosen cell (Phase 1: eng-low-risk backend, ceo-office-low-risk frontend)per-cartridge override
cartridges/administrative/eng-low-risk (built; obs app)admin-confidential (audit-grade)
cartridges/engineering/eng-low-risk (built)eng-confidential, eng-high-risk
cartridges/ceo-office/ceo-office-low-risk (built)ceo-office-confidential, ceo-office-high-risk
cartridges/sales/sales-low-risk (build when needed)sales-high-risk (PII customer data)
cartridges/marketing/marketing-low-risk
cartridges/hr/(skip low; HR almost always confidential)hr-confidential (employee data)
cartridges/finance/finance-low-riskfinance-high-risk, finance-confidential
cartridges/labs/labs-low-risk (sandbox; ephemeral)

The departmental axis is the right organizing principle for both data classification (CMKs) and app ownership (cartridges). The substrate and the cartridges share the same vocabulary.

7. Doctrine

§22 (recap): Cartridges segment by owning department

Folder = ownership. Group-claim = access. Cross-department apps still live under the owner department's folder; visibility is controlled at the AppMenu / Cognito group level.

Step 6.d doctrine: "Structure matches authority, not consumption."

The repo's folder structure encodes who can write what — that's authority. Who consumes an app is determined at run time via Cognito groups — that's consumption. Conflating the two leads to either over-permissive write access or under-discoverable apps. Separating them lets the same app be owned by one department and consumed by many.