41 KiB
Repository and microservice reorganization — specification
| Field | Value |
|---|---|
| Author | Anton Afanasyeu |
| Revision | R1 |
| Creation date | 2026-06-18 |
| Last modification date | 2026-06-22 |
| Co-authored | Cursor Agent (project assistant) |
| Severity | high |
| State | accepted |
| Document type | spec |
| Supersedes | — |
| Design review | docs/DRs/20260618_repos_reorganizing.md (frozen R1.1) |
Document type: SPEC
Source draft: docs/drafts/20260618_repos_reorganizing.txt
Design review: docs/DRs/20260618_repos_reorganizing.md (frozen)
PDF: 20260618_repos_reorganizing.pdf · Regenerate: bash scripts/build-all-docs-pdf.sh
Status: Accepted — implementation phased per §9; monolith remains deployable until each migration step completes
Scope: Split git://f0xx.org/android_cast monolith into git org ac on the f0xx.org git server — full microservice end-state, VM-first cloud path
Related: INFRA.md · BUILD_DEPLOY.md · specs/20100612_1_scaling.md · orchestration/sim/cluster0/ARCHITECTURE.md
Documentation index: README.md
VCS (normative): Canonical remotes are git://f0xx.org/ac/<repo> — repos are created on the PO git server (bare repos, hooks, ACLs). Gitea at …/git/ is a browse UI over mirrors only. Optional HTTPS read-only: Appendix B.
Table of contents
- 1. Purpose
- 2. Scope
- 3. Requirements
- 4. Baseline (current monolith)
- 5. Target architecture
- 6. Git repository catalog
- 7. Public URL specification
- 8. Dependency graphs
- 9. Migration plan
- 10. Infrastructure and cloud
- 11. ac-workspace and OTA versioning
- 12. Verification and acceptance
- 13. Risks and mitigations
- 14. Related documents
- 15. Changelog
- Appendix A — Git disk paths and remotes
- Appendix B — Optional HTTPS read-only git access
1. Purpose
Define the normative end-state and ordered migration for splitting the AndroidCast monolith (git://f0xx.org/android_cast) into:
- Independent git repositories under org
acon the f0xx.org git server - Microservice APIs (OpenAPI) and thin backend UIs
- One public URI root per microproject under
https://apps.f0xx.org/app/androidcast_project/ - Phased delivery without a forced big-bang during alpha
Identity gate: ac-ms-identity (migration Step 6) MUST complete before any other domain microservice split.
2. Scope
| In scope | Out of scope (this SPEC) |
|---|---|
| Repo catalog, disk paths, git remotes (Appendix A) | K8s / service mesh (optional later) |
| Path-per-microproject URL map (§7) | SFU/media transcode runtime (F1/F2 repos listed only) |
| 13-step migration plan (§9) | Rewriting mobile codec stack |
| Platform libs (Composer) before MS split | Gitea as repo provisioning UI |
| Optional HTTPS read-only git (Appendix B) | Merging AndroidCast with unrelated git hosting products |
| ac-workspace manifest + OTA multi-repo SHAs | Unified monorepo build in ac-workspace |
| VM lift-and-shift mapping to scaling SPEC | |
Unrelated nested git trees under examples/ (not product submodules) |
Git submodules (monolith → split): only third-party/* (mobile deps) and backend/url-shortener.
Alpha: Production MAY continue on the monolith until migration Step 8+ per service; each step MUST leave prior steps deployable.
3. Requirements
3.1 Must
| ID | Requirement |
|---|---|
| R-VCS-1 | Canonical remote: git://f0xx.org/ac/<repo>; PO creates bare repos on git server |
| R-VCS-2 | Gitea at …/git/ is browse-only mirror; agents MUST NOT provision repos in Gitea |
| R-URL-1 | Public base prefix: /app/androidcast_project/ |
| R-URL-2 | Target URLs MUST NOT use /crashes/ or ?view= (legacy 301 only, ≥ one release) |
| R-URL-3 | One path root per microproject (§7.2) |
| R-URL-4 | Auth at project root: /login, /logout, /register, /two-factor, /verify-email |
| R-ARCH-1 | Full microservice end-state per §5–§6 |
| R-ARCH-2 | ac-ms-identity gate before domain MS extraction (Step 6) |
| R-ARCH-3 | ac-scripts separate; ac-deploy consumes it |
| R-MIG-1 | Migration steps §9 executed in order; gates MUST NOT be skipped |
| R-SUB-1 | Monolith submodules: only third-party/* and backend/url-shortener |
| R-SUB-2 | No other nested git submodules in product repos or ac-workspace manifests |
| R-TEST-1 | Each step verification in §9 and §12 MUST pass before the next step starts |
3.2 Should
| ID | Requirement |
|---|---|
| R-VCS-3 | Optional HTTPS read-only clones via git-r.f0xx.org (Appendix B) |
| R-VCS-4 | Disk layout ac/<repo> under configurable GIT_ROOT (default /var/git/) |
| R-URL-5 | Cookie path /app/androidcast_project until SSO replaces shared PHP session |
| R-DOC-1 | OpenAPI stubs per MS in ac-docs/openapi/ after Step 4 |
3.3 Non-goals
- Big-bang cutover before identity MS and edge shell exist
ac-ms-vcsapplication repo (VCS is infrastructure)https://f0xx.org/...as git smart HTTP endpoint- AndroidCast code reading
/etc/git-ro/token ACL files (Appendix B is ops-only)
4. Baseline (current monolith)
4.1 Monolith map
| Monolith path | Future repo(s) | Notes |
|---|---|---|
app/, ndk/, gradle/ |
ac-mobile-android | third-party submodules |
desktop/session-studio/ |
ac-session-studio | Low coupling |
docs/ |
ac-docs | |
scripts/ |
ac-scripts | |
orchestration/ |
ac-deploy | cluster0, docker |
examples/crash_reporter/backend/ |
ac-ms-* + ac-be-* | 32 PHP classes, 24 APIs |
examples/build_console/ |
ac-ms-build, ac-be-builder | Same DB users |
examples/app_hub/ |
ac-be-hub | Loads shared platform-web assets (not /crashes/assets/) |
backend/url-shortener/ |
ac-ms-url-shortener | Existing submodule |
4.2 What is not a git repo
- Gitea — read-only web UI over git mirrors on BE (
:3000); not where repos are created - MariaDB, Janus (:8089)
4.3 Git submodules (monolith — only these)
| Path | Role after split |
|---|---|
third-party/* |
Native/codec deps (submodules of ac-mobile-android) |
backend/url-shortener/ |
URL shortener → ac-ms-url-shortener |
No other directories in the monolith carry git submodules. Post-split, ac-deploy may submodule ac-scripts (repo-to-repo pin).
5. Target architecture
Platform (Composer / static — not runtime MS)
ac-platform-php, ac-platform-db, ac-platform-web, ac-scripts, ac-docs
Infrastructure
ac-deploy submodules ac-scripts; docker, cluster0, nginx
ac-platform-edge nginx BFF: routes + session cookie domain
ac-workspace optional clone manifest (no unified build)
Clients
ac-mobile-android, ac-mobile-ios (future), ac-session-studio
Microservices (OpenAPI)
ac-ms-identity → ac-ms-rbac → ac-ms-devices
ac-ms-issues, ac-ms-tickets, ac-ms-graphs, ac-ms-remote-access
ac-ms-url-shortener, ac-ms-build, ac-ms-ota, ac-ms-notifications (later)
Backend UI (thin → MS APIs)
ac-be-hub, ac-be-issues, ac-be-tickets, ac-be-graphs,
ac-be-remote-access, ac-be-access, ac-be-builder, ac-be-auth
Consolidations vs initial PO sketch:
| Initial name | R0 decision |
|---|---|
| ac-be-console (monolith) | Dissolved into ac-be-issues … ac-be-access |
| ac-ms-tracker | ac-ms-issues + ac-ms-tickets |
| ac-ms-vpn-rssh + ac-ms-vpn-wireguard | ac-ms-remote-access (single control plane) |
| ac-ms-analytics | ac-ms-graphs (+ BI later) |
| ac-ms-orchestration | ac-ms-build + ac-deploy |
| ac-ms-vcs | Not a repo — Gitea is infra/UI only; git server is source of truth |
6. Git repository catalog
Canonical remote: git://f0xx.org/ac/<repo> — PO provisions bare repos on the git server (org namespace ac).
Browse UI (optional): https://apps.f0xx.org/app/androidcast_project/git/ac/<repo> — Gitea mirror for humans; push/fetch use git server.
Legacy: git://f0xx.org/android_cast → read-only mirror until retired.
6.1 Structure rationale (R1)
The catalog below is the recommended end-state for this project:
- Platform libs (P*) before microservices — avoids auth/DB duplication across 10+ PHP trees.
- Thin BE UI (B*) separate from MS APIs (S*) — matches PO’s one public URI per microproject (§7).
- ac-deploy + ac-scripts as the only deploy orchestration entry — fits VM roles in scaling SPEC.
- No
ac-ms-vcsrepo — VCS is infrastructure, not application code.
PO’s initial sketch used deeper folder names (ac-backend/*, ac-microservice/*). R1 keeps the flatter ac-<name> list — easier permissions, clone URLs, and OTA manifest entries. Minor renames are acceptable; dependency order and URI split are locked.
| ID | Repo | Git URL | Role |
|---|---|---|---|
| W0 | ac-workspace | git://f0xx.org/ac/ac-workspace |
Optional submodule manifest |
| P0 | ac-platform-php | git://f0xx.org/ac/ac-platform-php |
Composer: auth client, PDO, HTTP |
| P1 | ac-platform-db | git://f0xx.org/ac/ac-platform-db |
SQL migrations |
| P2 | ac-platform-web | git://f0xx.org/ac/ac-platform-web |
Shared CSS/JS/theme |
| P3 | ac-platform-edge | git://f0xx.org/ac/ac-platform-edge |
nginx routes + proxy |
| P4 | ac-scripts | git://f0xx.org/ac/ac-scripts |
CI, OTA, native codecs, PDF |
| P5 | ac-docs | git://f0xx.org/ac/ac-docs |
Documentation |
| D0 | ac-deploy | git://f0xx.org/ac/ac-deploy |
docker, cluster0; uses P4 |
| C0 | ac-mobile-android | git://f0xx.org/ac/ac-mobile-android |
Android + ndk + third-party |
| C1 | ac-mobile-ios | git://f0xx.org/ac/ac-mobile-ios |
Future iOS |
| C2 | ac-session-studio | git://f0xx.org/ac/ac-session-studio |
Desktop analyzer |
| S0 | ac-ms-template | git://f0xx.org/ac/ac-ms-template |
New MS cookiecutter |
| S1 | ac-ms-identity | git://f0xx.org/ac/ac-ms-identity |
Users, login, 2FA, sessions |
| S2 | ac-ms-rbac | git://f0xx.org/ac/ac-ms-rbac |
Companies, privileges |
| S3 | ac-ms-devices | git://f0xx.org/ac/ac-ms-devices |
Device registry |
| S4 | ac-ms-issues | git://f0xx.org/ac/ac-ms-issues |
Crash/report ingest |
| S5 | ac-ms-tickets | git://f0xx.org/ac/ac-ms-tickets |
Ticket workflow |
| S6 | ac-ms-graphs | git://f0xx.org/ac/ac-ms-graphs |
Graph ingest/query |
| S7 | ac-ms-remote-access | git://f0xx.org/ac/ac-ms-remote-access |
WG + RSSH API |
| S8 | ac-ms-url-shortener | git://f0xx.org/ac/ac-ms-url-shortener |
Short links API |
| S9 | ac-ms-build | git://f0xx.org/ac/ac-ms-build |
Build worker API |
| S10 | ac-ms-ota | git://f0xx.org/ac/ac-ms-ota |
Channel manifests |
| S11 | ac-ms-notifications | git://f0xx.org/ac/ac-ms-notifications |
SMTP (post-alpha) |
| B0 | ac-be-hub | git://f0xx.org/ac/ac-be-hub |
Landing |
| B1 | ac-be-issues | git://f0xx.org/ac/ac-be-issues |
Issues UI |
| B2 | ac-be-tickets | git://f0xx.org/ac/ac-be-tickets |
Tickets UI |
| B3 | ac-be-graphs | git://f0xx.org/ac/ac-be-graphs |
Graphs UI |
| B4 | ac-be-remote-access | git://f0xx.org/ac/ac-be-remote-access |
RA admin UI |
| B5 | ac-be-access | git://f0xx.org/ac/ac-be-access |
RBAC admin UI |
| B6 | ac-be-builder | git://f0xx.org/ac/ac-be-builder |
Builder UI |
| B7 | ac-be-auth | git://f0xx.org/ac/ac-be-auth |
Login/register shell |
| F1 | ac-ms-sfu-signaling | git://f0xx.org/ac/ac-ms-sfu-signaling |
Future F1 |
| F2 | ac-ms-media-transcode | git://f0xx.org/ac/ac-ms-media-transcode |
Future VOD |
Third-party codecs remain submodules of C0 (upstream URLs); optional git-server mirrors under ac/ for backup (sync scripts, not Gitea-as-SoT).
6.2 Repo creation waves (git server)
PO creates bare repos on the git server in waves (Gitea mirror sync follows). Agent/docs do not “create repos in Gitea.”
flowchart LR
W1[Wave 1: docs scripts deploy session-studio url-shortener] --> W2[Wave 2: platform-php platform-db platform-web]
W2 --> W3[Wave 3: ms-identity]
W3 --> W4[Wave 4: ms-rbac ms-devices]
W4 --> W5[Wave 5: ms-issues ms-tickets + be UI]
W5 --> W6[Wave 6: ms-graphs ms-remote-access ms-build + UI]
W6 --> W7[Wave 7: platform-edge mobile-android ms-ota]
7. Public URL specification
Base prefix (locked): https://apps.f0xx.org/app/androidcast_project
7.1 Rules (R1 — PO locked)
- No
/crashes/in target URLs — legacy path 301 → correct microproject root for ≥ one release, then drop from nginx/docs/mobile. - No
?view=routing — each product surface has its own path root and (eventually) its own BE UI repo + nginxlocation. - Auth at project root —
/login,/logout,/register,/two-factor,/verify-email(not under/issues/). - Shared cookie path —
/app/androidcast_projectat ac-platform-edge until SSO tokens replace shared PHP session.
7.2 Target path catalog (one URI per microproject)
| Microproject | Target URL root | Repo (UI / API) | Notes |
|---|---|---|---|
| Hub / landing | …/ |
ac-be-hub | Entry cards link to path roots only |
| Auth | …/login, …/logout, … |
ac-be-auth → ac-ms-identity | Project-root paths |
| Issues (reports) | …/issues/ |
ac-be-issues / ac-ms-issues | Was ?view=reports |
| Issue detail | …/issues/{id} |
ac-be-issues | Was ?view=report&id= |
| Tickets | …/tickets/ |
ac-be-tickets / ac-ms-tickets | Was ?view=tickets |
| Ticket detail | …/tickets/{id} |
ac-be-tickets | Was ?view=ticket&id= |
| Analytics / graphs | …/graphs/ |
ac-be-graphs / ac-ms-graphs | Already separate |
| RBAC / access | …/access/ |
ac-be-access / ac-ms-rbac | Was ?view=rbac |
| Remote access | …/remote-access/ |
ac-be-remote-access / ac-ms-remote-access | Was ?view=remote_access |
| Short links | …/short-links/ |
ac-be-hub or thin UI / ac-ms-url-shortener | Was ?view=short_links |
| Live sessions | …/live-sessions/ |
ac-be-issues (or ac-be-live) / live_cast API | Was ?view=live_sessions |
| Live join / education | …/live/join, …/live/education |
shared live pages | Under issues until split |
| Builder | …/build/ |
ac-be-builder / ac-ms-build | Unchanged |
| Git browse | …/git/ |
Gitea UI (mirror) | Not a microservice repo |
| OTA | /v0/ota/ |
ac-ms-ota | Top-level on apps host |
API examples: …/issues/api/upload (not …/crashes/api/upload.php).
7.3 Migration table (legacy → target)
| Legacy (forbidden in target) | Target URL |
|---|---|
…/crashes/?view=reports |
…/issues/ |
…/crashes/?view=report&id=N |
…/issues/N |
…/crashes/?view=tickets |
…/tickets/ |
…/crashes/?view=ticket&id=N |
…/tickets/N |
…/crashes/?view=home |
…/issues/ or …/ (hub) |
…/crashes/?view=rbac |
…/access/ |
…/crashes/?view=remote_access |
…/remote-access/ |
…/crashes/?view=short_links |
…/short-links/ |
…/crashes/?view=live_sessions |
…/live-sessions/ |
…/crashes/?view=graphs |
…/graphs/ |
…/crashes/login |
…/login |
…/crashes/api/upload.php |
…/issues/api/upload |
…/crashes/ (any) |
301 → matching row above |
Monolith shim (Step 5 only): nginx may internally rewrite /issues/ → legacy PHP ?view=reports until ac-ms-issues exists — not exposed in links, docs, or mobile defaults.
Code updates: BackendEndpoints.java, hub index.php, all console nav, OpenAPI base paths, deploy nginx fragments.
8. Dependency graphs
8.1 End-to-end — clients, edge, services
flowchart TB
subgraph clients [Clients]
AND[ac-mobile-android]
IOS[ac-mobile-ios]
HUB[ac-be-hub]
SS[ac-session-studio]
end
subgraph edge [Edge]
EDGE[ac-platform-edge]
end
subgraph core [Core MS — order matters]
ID[ac-ms-identity]
RB[ac-ms-rbac]
DV[ac-ms-devices]
end
subgraph domain [Domain MS]
IS[ac-ms-issues]
TK[ac-ms-tickets]
GR[ac-ms-graphs]
RA[ac-ms-remote-access]
UL[ac-ms-url-shortener]
BL[ac-ms-build]
OT[ac-ms-ota]
end
AND --> EDGE
IOS --> EDGE
HUB --> EDGE
SS -.->|offline files| AND
EDGE --> ID
EDGE --> IS & TK & GR & RA & UL & BL & OT & RB
ID --> RB
RB --> DV
IS --> DV & RB
TK --> RB
TK -.-> IS
GR --> ID
RA --> RB & DV
RA -.-> IS
UL --> RB
BL --> ID
OT --> BL
OT --> AND & IOS
8.2 Backend UI → microservice (requires)
flowchart LR
B7[ac-be-auth] --> S1[ac-ms-identity]
B5[ac-be-access] --> S2[ac-ms-rbac]
B1[ac-be-issues] --> S4[ac-ms-issues]
B2[ac-be-tickets] --> S5[ac-ms-tickets]
B3[ac-be-graphs] --> S6[ac-ms-graphs]
B4[ac-be-remote-access] --> S7[ac-ms-remote-access]
B6[ac-be-builder] --> S9[ac-ms-build]
B0[ac-be-hub] --> S1
B0 --> P2[ac-platform-web]
S4 --> S3[ac-ms-devices]
S4 --> S2
S5 --> S2
S7 --> S2 & S3
Every B* and S* also requires P0 (ac-platform-php) and P1 (ac-platform-db) via Composer — omitted from diagram for clarity.
8.3 Platform and deploy layer
flowchart TB
D0[ac-deploy] --> P4[ac-scripts]
D0 --> P3[ac-platform-edge]
D0 --> P1[ac-platform-db]
P3 -->|routes| S1 & S4 & S5 & S6 & S7 & S8 & S9 & S10
P2[ac-platform-web] -->|static| B0 & B1 & B2
S1 & S2 & S3 & S4 & S5 --> P0[ac-platform-php]
S6 & S7 & S8 & S9 & S10 --> P0
B0 & B1 & B2 & B3 & B4 & B5 & B6 & B7 --> P0
P1 --> DB[(MariaDB / managed DB)]
S11[ac-ms-notifications] -.->|mail| S1
8.4 Service dependency matrix
| Service | Requires (hard) | Requires (soft) | Required by |
|---|---|---|---|
| ac-platform-db | — | — | All MS, migration jobs |
| ac-platform-php | ac-platform-db | — | All MS, all BE UI |
| ac-platform-web | — | — | ac-be-hub, all BE UI |
| ac-platform-edge | ac-deploy nginx templates | all MS upstream addrs | All public HTTP |
| ac-ms-identity | platform-db, platform-php | ac-ms-notifications | All MS, all BE UI, ac-ms-build |
| ac-ms-rbac | ac-ms-identity | — | devices, issues, tickets, RA, url-shortener |
| ac-ms-devices | ac-ms-rbac | ac-ms-identity | ac-ms-issues, ac-ms-remote-access |
| ac-ms-issues | ac-ms-rbac, ac-ms-devices | — | ac-be-issues, mobile upload |
| ac-ms-tickets | ac-ms-rbac | ac-ms-issues | ac-be-tickets |
| ac-ms-graphs | ac-ms-identity | — | ac-be-graphs, mobile |
| ac-ms-remote-access | ac-ms-rbac, ac-ms-devices | ac-ms-issues | ac-be-remote-access, mobile |
| ac-ms-url-shortener | ac-ms-rbac | — | hub/admin UI |
| ac-ms-build | ac-ms-identity | git server mirrors | ac-be-builder, ac-ms-ota |
| ac-ms-ota | ac-ms-build | C0, C1 SHAs | mobile OTA clients |
| ac-mobile-android | ac-ms-issues, ac-ms-graphs, ac-ms-remote-access APIs | ac-ms-ota | — |
8.5 Repo creation waves
See §6.2 for the ordered wave diagram.
9. Migration plan
Ordered steps for converting the monolith. Do not skip gates. Each step lists repos created/moved, monolith paths affected, and verification (see also §12).
Step 1 — Git org ac on f0xx.org server (no code move)
Goal: Namespace ac exists on the git server; legacy monolith mirror preserved; Gitea browse UI synced.
| Action | Detail |
|---|---|
| Create org / paths | PO: bare repos under git://f0xx.org/ac/<repo> on git server |
| Mirror | android_cast → read-only; plan ac-workspace or retire later |
| Gitea (optional) | Sync mirrors for …/git/ browse UI only — not repo creation |
| Update docs | Pointer in INFRA.md, AGENTS.md |
Verify: git ls-remote git://f0xx.org/ac/ac-docs (after Step 2) ; legacy push still works.
Requires: nothing
Enables: all following steps
Step 2 — Extract zero-coupling repos
Goal: Repos with no runtime dependency on PHP monolith.
| Repo | From monolith | CI |
|---|---|---|
| ac-docs | docs/ |
PDF build |
| ac-scripts | scripts/ |
lint/smoke |
| ac-session-studio | desktop/session-studio/ |
unit tests |
| ac-ms-url-shortener | backend/url-shortener/ |
PHPUnit (change remote URL only if already split) |
| ac-deploy | orchestration/ + nginx seeds |
docker compose smoke |
ac-deploy submodules ac-scripts at pinned SHA.
Verify: Each repo builds independently; monolith submodule paths updated OR mirror dual-push during transition.
Requires: Step 1
Enables: Steps 3–4
Step 3 — Platform libraries (foundation)
Goal: Shared code leaves monolith as Composer packages — no MS split yet.
| Repo | Extract from |
|---|---|
| ac-platform-db | sql/, migrations from crash_reporter + url-shortener |
| ac-platform-php | Auth*, Database, Rbac helpers, bootstrap patterns, shared_session.php |
| ac-platform-web | crashes/assets/, shared theme referenced by hub |
Monolith requires packages via Composer; behavior unchanged.
Verify: Monolith tests green; single login still works across hub/crashes/build.
Requires: Step 2
Enables: Step 4 (identity)
Step 4 — Microservice template and OpenAPI baseline
Goal: Cookiecutter + contract layout for all MS.
| Repo | Action |
|---|---|
| ac-ms-template | Copy url-shortener + platform-php wiring |
| ac-docs | Add openapi/ stubs per service |
Verify: Scaffold new empty MS from template; deploy locally via ac-deploy.
Requires: Step 3
Enables: Step 5
Step 5 — Edge proxy (routing shell)
Goal: ac-platform-edge nginx config routes paths; still proxies to monolith PHP until MS exist.
| Action | Detail |
|---|---|
| Deploy edge config | Map /issues/ → monolith ?view=reports internally (temporary) |
| Cookie | Single path /app/androidcast_project |
Verify: curl -I new paths return 200 via rewrite; old URLs still work.
Requires: Step 2 (ac-deploy)
Enables: Step 10 URL cutover
Step 6 — Identity microservice (GATE)
Goal: ac-ms-identity owns users, login, register, 2FA, session issuance.
| Repo | From monolith |
|---|---|
| ac-ms-identity | Auth*, UserRepository, AuthTotp*, AuthRegistration*, … |
| ac-be-auth | login/register views (thin) |
Monolith/builder call identity for auth (HTTP or shared session bridge during transition).
Verify: Login at /app/androidcast_project/ + builder; sessions valid; ./scripts/test_rbac_api.sh still passes against bridged auth.
Requires: Steps 3, 4
Enables: Steps 7, 9, 11 — nothing else splits before this
Step 7 — RBAC and devices microservices
Goal: Company scope and device registry are independent APIs.
| Repo | From monolith |
|---|---|
| ac-ms-rbac | Rbac*, RbacAdmin*, companies API |
| ac-ms-devices | DeviceRepository |
Verify: Upload still registers device; RBAC panel works via APIs.
Requires: Step 6
Enables: Steps 8, 9
Step 8 — Issues and tickets (domain core)
Goal: Split PO’s primary URL surfaces.
| Repo | From monolith |
|---|---|
| ac-ms-issues | upload, Report*, Tag*, reports API |
| ac-ms-tickets | Ticket*, attachments |
| ac-be-issues | reports views + JS |
| ac-be-tickets | tickets views + JS |
Edge routes /issues/ → S4/B1, /tickets/ → S5/B2.
Verify: Mobile upload to new URL; web issue/ticket lists; E2E ticket workflow.
Requires: Step 7
Enables: Step 9 (RA links to issues)
Step 9 — Graphs and remote access
| Repo | From monolith |
|---|---|
| ac-ms-graphs | GraphRepository, graph_* API |
| ac-ms-remote-access | RemoteAccess*, WireGuard*, Rssh* |
| ac-be-graphs | graphs UI |
| ac-be-remote-access | remote_access view |
Verify: BackendEndpoints graph URL; RA E2E (ra_e2e_cli.sh); mobile RA API.
Requires: Steps 7, 8 (RA → devices, issue links)
Enables: Step 11
Step 10 — Hub, access UI, URL migration
| Repo | Action |
|---|---|
| ac-be-hub | Extract app_hub; use ac-platform-web assets |
| ac-be-access | RBAC UI → calls ac-ms-rbac |
| ac-platform-edge | Enable 301 from /crashes/ and ?view=* to §7 path roots |
Verify: Hub cards link to /issues/, /tickets/; no broken CSS.
Requires: Steps 5, 8, 9
Enables: Step 11
Step 11 — Build and OTA pipeline
| Repo | From monolith |
|---|---|
| ac-ms-build | BuildRunner, build APIs |
| ac-be-builder | build_console UI |
| ac-ms-ota | OTA manifest assembly |
| ac-mobile-android | app/, ndk/, gradle (extract from monolith) |
Verify: Builder triggers APK; OTA channel publishes; manifest lists android (+ ios when C1 exists).
Requires: Step 6 (identity for builder users)
Enables: Step 12
Step 12 — Optional workspace and monolith retirement
| Action | Detail |
|---|---|
| ac-workspace | Publish optional .gitmodules manifest |
| Retire | Stop commits to android_cast monolith; archive mirror |
| Gitea mirror sync | Update mirror scripts for org ac (server → Gitea UI; gitea README) |
Verify: Fresh clone via ac-workspace or individual repos; prod deploy from ac-deploy only.
Requires: Steps 1–11 complete for services in scope
Enables: cloud VM scaling, future F1/F2 MS
Step 13 — Notifications and cloud hardening (post-alpha)
| Repo | Action |
|---|---|
| ac-ms-notifications | Extract AuthMailer; wire 2.x mail when unblocked |
| ac-deploy | Managed DB DSN templates; cluster0 → cloud VM roles |
Requires: Step 6; mail infra (developer)
Enables: full 2FA mail E2E
Conversion step summary (quick reference)
| Step | Name | Gate |
|---|---|---|
| 1 | Git org ac on server |
— |
| 2 | docs, scripts, deploy, session-studio, url-shortener | — |
| 3 | platform-php, platform-db, platform-web | — |
| 4 | ms-template, OpenAPI | — |
| 5 | platform-edge (shell) | — |
| 6 | ms-identity, be-auth | GATE |
| 7 | ms-rbac, ms-devices | after 6 |
| 8 | ms-issues, ms-tickets, be-issues, be-tickets | after 7 |
| 9 | ms-graphs, ms-remote-access, be UI | after 7–8 |
| 10 | be-hub, be-access, URL 301 | after 8–9 |
| 11 | ms-build, ms-ota, mobile-android | after 6 |
| 12 | ac-workspace, retire monolith | after 1–11 |
| 13 | notifications, cloud | post-alpha |
10. Infrastructure and cloud
| Stage | Pattern |
|---|---|
| Prod today | FE TLS → BE :80 nginx + PHP-FPM + MariaDB |
| cluster0 lab | cast01–03; NFS config only; GTID DB (ARCHITECTURE.md) |
| Cloud phase A | 4–6 VMs: be-web, be-data, be-ops, be-build (scaling §6.3) |
| Cloud phase B | Managed DB; DSN in secrets (not in git) |
| Cloud phase C | K8s optional — not required at R0 |
Inter-service calls: HTTP on private VLAN / localhost initially; OpenAPI in ac-docs. No service mesh at R0.
ac-deploy ships Ansible/docker-compose per VM role; submodules ac-scripts.
11. ac-workspace and OTA versioning
ac-workspace — optional; lists repo SHAs for a release train. Not a unified Gradle/PHP build.
ac-ms-ota manifest (same product version, per-platform SHAs):
{
"channel": "staging",
"version": "00.02.00.00",
"artifacts": {
"android": { "repo": "ac-mobile-android", "git_sha": "abc123" },
"ios": { "repo": "ac-mobile-ios", "git_sha": "def456" }
}
}
12. Verification and acceptance
Per-step gates from §9 — all MUST pass before the next step begins.
| Step | Acceptance criteria |
|---|---|
| 1 | git ls-remote git://f0xx.org/ac/ac-docs succeeds (after Step 2 repo exists); legacy android_cast push still works |
| 2 | Each extracted repo builds/CI green independently |
| 3 | Monolith tests green; single login across hub/issues/build |
| 4 | Empty MS scaffold deploys locally via ac-deploy |
| 5 | curl -I on /issues/, /tickets/, … return 200 via edge rewrite |
| 6 | Login + ./scripts/test_rbac_api.sh pass (identity gate) |
| 7 | Device upload + RBAC API via new services |
| 8 | Mobile upload to …/issues/api/upload; ticket E2E |
| 9 | Graph + RA E2E (ra_e2e_cli.sh) |
| 10 | Hub links use path roots only; 301 from /crashes/ |
| 11 | Builder APK + OTA channel publish |
| 12 | Fresh clone via ac-workspace or per-repo remotes |
| 13 | Mail E2E when infra unblocked |
URL regression (ongoing): hub, mobile BackendEndpoints, nginx fragments, and docs MUST NOT introduce new /crashes/ or ?view= links after Step 5.
Repo index: Appendix A disk paths MUST match live git server layout before Step 2 mass extract.
13. Risks and mitigations
| Risk | Mitigation |
|---|---|
| Auth split breaks all consoles | Step 6 gate; session bridge during transition |
| Hub broken CSS | ac-platform-web before ac-be-hub (Step 3 before 10) |
| Mobile upload URL change | Parallel endpoints + BackendEndpoints normalization |
| DB schema drift | ac-platform-db single migration stream |
| Too many repos to bump | Composer semver for P0; not @common submodule diamond |
| Alpha blocked | Monolith stays prod until Step 8+ complete per service |
| PO BE learning curve | ac-ms-template, ac-deploy, OpenAPI, localhost HTTP |
Appendix A — Git disk paths and remotes
Convention: disk paths are relative to the git server root (example: /var/git/). PO may choose another root; keep the ac/<repo> layout.
Canonical clone/fetch (write + read): git://f0xx.org/ac/<repo>
HTTPS read-only (optional): see Appendix B — separate vhost; not https://f0xx.org/... app URLs.
| # | Disk path (relative) | Git repo URL |
|---|---|---|
| 1 | ac/ac-workspace |
git://f0xx.org/ac/ac-workspace |
| 2 | ac/ac-platform-php |
git://f0xx.org/ac/ac-platform-php |
| 3 | ac/ac-platform-db |
git://f0xx.org/ac/ac-platform-db |
| 4 | ac/ac-platform-web |
git://f0xx.org/ac/ac-platform-web |
| 5 | ac/ac-platform-edge |
git://f0xx.org/ac/ac-platform-edge |
| 6 | ac/ac-scripts |
git://f0xx.org/ac/ac-scripts |
| 7 | ac/ac-docs |
git://f0xx.org/ac/ac-docs |
| 8 | ac/ac-deploy |
git://f0xx.org/ac/ac-deploy |
| 9 | ac/ac-mobile-android |
git://f0xx.org/ac/ac-mobile-android |
| 10 | ac/ac-mobile-ios |
git://f0xx.org/ac/ac-mobile-ios |
| 11 | ac/ac-session-studio |
git://f0xx.org/ac/ac-session-studio |
| 12 | ac/ac-ms-template |
git://f0xx.org/ac/ac-ms-template |
| 13 | ac/ac-ms-identity |
git://f0xx.org/ac/ac-ms-identity |
| 14 | ac/ac-ms-rbac |
git://f0xx.org/ac/ac-ms-rbac |
| 15 | ac/ac-ms-devices |
git://f0xx.org/ac/ac-ms-devices |
| 16 | ac/ac-ms-issues |
git://f0xx.org/ac/ac-ms-issues |
| 17 | ac/ac-ms-tickets |
git://f0xx.org/ac/ac-ms-tickets |
| 18 | ac/ac-ms-graphs |
git://f0xx.org/ac/ac-ms-graphs |
| 19 | ac/ac-ms-remote-access |
git://f0xx.org/ac/ac-ms-remote-access |
| 20 | ac/ac-ms-url-shortener |
git://f0xx.org/ac/ac-ms-url-shortener |
| 21 | ac/ac-ms-build |
git://f0xx.org/ac/ac-ms-build |
| 22 | ac/ac-ms-ota |
git://f0xx.org/ac/ac-ms-ota |
| 23 | ac/ac-ms-notifications |
git://f0xx.org/ac/ac-ms-notifications |
| 24 | ac/ac-be-hub |
git://f0xx.org/ac/ac-be-hub |
| 25 | ac/ac-be-issues |
git://f0xx.org/ac/ac-be-issues |
| 26 | ac/ac-be-tickets |
git://f0xx.org/ac/ac-be-tickets |
| 27 | ac/ac-be-graphs |
git://f0xx.org/ac/ac-be-graphs |
| 28 | ac/ac-be-remote-access |
git://f0xx.org/ac/ac-be-remote-access |
| 29 | ac/ac-be-access |
git://f0xx.org/ac/ac-be-access |
| 30 | ac/ac-be-builder |
git://f0xx.org/ac/ac-be-builder |
| 31 | ac/ac-be-auth |
git://f0xx.org/ac/ac-be-auth |
| 32 | ac/ac-ms-sfu-signaling |
git://f0xx.org/ac/ac-ms-sfu-signaling |
| 33 | ac/ac-ms-media-transcode |
git://f0xx.org/ac/ac-ms-media-transcode |
| 34 | android_cast |
git://f0xx.org/android_cast |
Bare repo on server (PO): git init --bare /var/git/ac/ac-workspace (repeat per row; path = {GIT_ROOT}/ + disk path).
Appendix B — Optional HTTPS read-only git access
Scope: Standalone git infrastructure on the PO git host. Not part of the AndroidCast monorepo, BE PHP tree, Gitea product UI, or apps.f0xx.org consoles.
Goal: Keep git://f0xx.org/... for normal push/fetch; add https:// for read-only clones (anonymous and/or token), with TLS certs and ACL files outside the AndroidCast project.
Suggested hostname: git-r.f0xx.org (read-only smart HTTP). Do not reuse https://f0xx.org/ landing or https://apps.f0xx.org/ app paths for git smart HTTP.
Suggested paths on git server:
| Path | Purpose |
|---|---|
/var/git/ |
Bare repos (Appendix A disk layout) |
/etc/git-ro/ |
nginx snippets, token maps, install scripts — not in android_cast repo |
/etc/git-ro/tokens/ |
Per-token permission files (see step 8) |
/etc/letsencrypt/live/git-r.f0xx.org/ |
Certbot certificates |
1) DNS
Add an A (or AAAA) record for the read-only git vhost pointing at the git server public or edge IP (same host that serves git:// today, or FE DNAT to it):
git-r.f0xx.org. IN A <GIT_SERVER_PUBLIC_IP>
Verify:
dig +short git-r.f0xx.org
2) Install packages (git server — example: Gentoo/Alpine)
On the machine that holds /var/git/:
# Gentoo (example)
emerge -av nginx git fcgiwrap certbot
# Alpine (example)
apk add nginx git git-daemon fcgiwrap certbot certbot-nginx openssl
Enable fcgiwrap (smart HTTP via git http-backend):
# systemd example
systemctl enable --now fcgiwrap
3) Issue free TLS certificates (Certbot)
Run on the git server (or on FE if it terminates TLS and proxies to git — adjust plugin):
certbot certonly --standalone -d git-r.f0xx.org \
--agree-tos -m admin@f0xx.org --non-interactive
If nginx is already bound to :80/:443, use the nginx plugin instead:
certbot certonly --nginx -d git-r.f0xx.org \
--agree-tos -m admin@f0xx.org --non-interactive
Certificates land under /etc/letsencrypt/live/git-r.f0xx.org/fullchain.pem and privkey.pem.
4) nginx — HTTPS smart HTTP, read-only
Create /etc/git-ro/nginx-git-ro.conf (outside AndroidCast):
server {
listen 443 ssl;
server_name git-r.f0xx.org;
ssl_certificate /etc/letsencrypt/live/git-r.f0xx.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git-r.f0xx.org/privkey.pem;
root /var/git;
location ~ ^/ac/(.+?)(\.git)?/(HEAD|info/refs|objects/info/.*|objects/([0-9a-f]{2}/[0-9a-f]{38}|pack/pack-.*))$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;
fastcgi_param GIT_HTTP_EXPORT_ALL "";
fastcgi_param GIT_PROJECT_ROOT /var/git;
fastcgi_param PATH_INFO /$1.git/$2;
fastcgi_pass unix:/run/fcgiwrap.socket;
}
location ~ ^/ac/(.+?)\.git$ {
return 301 /ac/$1.git/info/refs?service=git-upload-pack;
}
}
Include it from the main nginx config:
ln -s /etc/git-ro/nginx-git-ro.conf /etc/nginx/conf.d/git-ro.conf
nginx -t && rc-service nginx reload # Gentoo
# nginx -t && systemctl reload nginx # other
Read-only guarantee: do not enable receive-pack; only git-upload-pack (clone/fetch) is exposed. Push stays on git://f0xx.org (SSH or authenticated path), not this vhost.
Test anonymous clone:
git clone https://git-r.f0xx.org/ac/ac-docs.git /tmp/ac-docs-ro-test
5) Mark public repos for anonymous HTTPS read
For each bare repo that may be cloned without a token:
GIT_ROOT=/var/git
repo=ac/ac-docs
touch "${GIT_ROOT}/${repo}.git/git-daemon-export-ok"
git -C "${GIT_ROOT}/${repo}.git" config http.receivepack false
git -C "${GIT_ROOT}/${repo}.git" config http.uploadpack true
Repeat for every Appendix A row you want world-readable over HTTPS.
6) Optional — require token for private HTTPS read
Add HTTP basic auth for selected locations. Store credentials outside AndroidCast:
install -d -m 0750 /etc/git-ro/htpasswd
htpasswd -c /etc/git-ro/htpasswd/ro-ci-user
In /etc/git-ro/nginx-git-ro.conf, inside the location block for smart HTTP:
auth_basic "git read-only";
auth_basic_user_file /etc/git-ro/htpasswd/ro-users;
Clone with token (password = token):
git clone https://ro-ci-user:<TOKEN>@git-r.f0xx.org/ac/ac-ms-identity.git
7) Token-wise permissions (outside AndroidCast)
Keep a simple ACL file per token under /etc/git-ro/tokens/ — not referenced by android_cast code:
install -d -m 0700 /etc/git-ro/tokens
cat > /etc/git-ro/tokens/ci-read-issues.env <<'EOF'
# token name: ci-read-issues
# htpasswd user: ro-ci-issues
# allowed repo prefixes (one per line, relative to /var/git)
ac/ac-ms-issues
ac/ac-be-issues
ac/ac-platform-php
EOF
chmod 0600 /etc/git-ro/tokens/*.env
Enforcement options (pick one on the git server):
- Simple: separate htpasswd users per token + nginx
locationblocks per repo prefix. - Scalable: small
git-ro-authscript (not in AndroidCast repo) consulted by nginxauth_request.
AndroidCast never reads /etc/git-ro/; CI machines hold tokens in their own secret stores.
8) Certbot renewal (crontab)
Edit root crontab on the git server:
crontab -e
Add:
17 3 * * * certbot renew --quiet --deploy-hook "nginx -t && rc-service nginx reload"
Or install a one-shot renew script /etc/git-ro/certbot-renew.sh:
#!/bin/sh
set -eu
certbot renew --quiet
nginx -t
rc-service nginx reload
chmod 0755 /etc/git-ro/certbot-renew.sh
crontab -e
17 3 * * * /etc/git-ro/certbot-renew.sh >> /var/log/git-ro-certbot.log 2>&1
9) Client remote examples
| Use case | Remote URL |
|---|---|
| Developer push/fetch (canonical) | git://f0xx.org/ac/ac-mobile-android |
| Anonymous read (HTTPS) | https://git-r.f0xx.org/ac/ac-docs.git |
| Token read (HTTPS) | https://<user>:<token>@git-r.f0xx.org/ac/ac-ms-issues.git |
| Browse HTML (optional) | https://apps.f0xx.org/app/androidcast_project/git/ (Gitea mirror only) |
Do not document https://f0xx.org/... as a git smart HTTP endpoint; landing stays human/PDF only.
10) Verification checklist
# TLS
curl -sSI https://git-r.f0xx.org/ac/ac-docs.git/info/refs?service=git-upload-pack | head
# git:// still works (unchanged)
git ls-remote git://f0xx.org/ac/ac-docs
# HTTPS read-only (no push)
git clone https://git-r.f0xx.org/ac/ac-docs.git /tmp/ro-clone-test
cd /tmp/ro-clone-test && git push origin HEAD # must fail on this vhost
14. Related documents
| Document | Role |
|---|---|
| DRs/20260618_repos_reorganizing.md | Frozen design review R1.1 (source of this SPEC) |
| INFRA.md | FE/BE topology, ports |
| BUILD_DEPLOY.md | Session cookie, deploy paths |
| specs/20100612_1_scaling.md | VM roles, cluster layout |
| orchestration/sim/cluster0/ARCHITECTURE.md | Lab cluster |
| OPEN_TASKS_GRAPH.md | Task dependencies |
15. Changelog
| Rev | Date | Change |
|---|---|---|
| R1 | 2026-06-22 | SPEC converted from frozen DR R1.1; normative requirements §3; migration §9; verification §12 |
| R1.1 | 2026-06-22 | Submodule policy §4.3: only third-party/* + backend/url-shortener |