Project repository and structure reorganization draft milestone: R0-pre severity: high state: pre-implementation author: Anton Afanasyeu date: 2026-06-18 [AI comment]: Updated 2026-06-18 — PO chose org **`ac`**, **full microservice** end-state, separate **ac-scripts**, URL path migration (§L), optional **ac-workspace** (not build-all-in-one), VM-first cloud (§N). See §G master repo table. The problem: The project looks like monolith. For better and more atomic support we need to reorganize the whole project repo structure [AI comment]: Agree on the problem, but **atomic** should mean: independent release cadence, CI, deploy, and rollback — not “one git repo per PHP class.” Today’s real coupling is **one MariaDB**, **one PHP session** (`ac_crash_sess`, [BUILD_DEPLOY.md](../BUILD_DEPLOY.md)), and **one nginx vhost tree** on BE. Split repos before extracting shared platform code will multiply broken deploys. ────────────────────────────────────────────────────────────────────────────── A. Current codebase map (monolith → draft names) ────────────────────────────────────────────────────────────────────────────── | Draft name / intent | Actual path today | Coupling notes | |---------------------|-------------------|----------------| | ac-mobile | `app/`, `ndk/`, `gradle/`, `build.gradle`, `settings.gradle` | WireGuard tunnel module; `third-party/*` submodules | | ac-session-studio | `desktop/session-studio/` | Standalone; low coupling — **easy first extract** | | ac-docs | `docs/` (+ `docs/_pdf_build/`) | No runtime deps — **easy extract** | | ac-scripts | `scripts/` (pdf, native codecs, OTA, CI helpers) | Used by mobile + orchestration; keep with **ac-deploy** or meta until split clear | | ac-be-console (crashes/issues/tickets/graphs/rbac/ra) | `examples/crash_reporter/backend/` | **32 PHP classes**, 24 `public/api/*.php`, shared `Auth.php`, `Database.php`, `Rbac.php` — **one modular monolith** | | ac-be-builder | `examples/build_console/backend/` | Separate app; shares auth pattern via `examples/platform/shared_session.php` + same DB users table | | ac-be-landing | `examples/app_hub/` | Static hub + deploy nginx snippets | | ac-be-ota (artifacts) | `examples/ota/v0/...` | Files on disk + nginx; logic also in builder + `scripts/generate-ota-v0.sh` | | ac-ms-url-shortener | `backend/url-shortener/` | **Only live submodule today** — `git://f0xx.org/androidcast_project/url-shortener` | | ac-deploy / orchestration | `orchestration/` (docker, cluster0, nginx, runtime) | Local stack + **cast01–03** lab ([orchestration/sim/cluster0/ARCHITECTURE.md](../../orchestration/sim/cluster0/ARCHITECTURE.md)) | | ac-ms-vpn / WG / RSSH | Mobile: `app/.../remoteaccess/`; BE: `RemoteAccessRepository.php`, `WireGuard*`, `Rssh*` provisioners | **Split by plane**: client in mobile, control API in BE console — not two deployables yet | | ac-ms-vcs (gitea) | `examples/crash_reporter/backend/scripts/gitea/` | **Ops scripts only** — Gitea is external service on BE, not app source | | ac-ms-tracker / analytics | `Ticket*`, `Graph*` repos in crash_reporter | Same DB + session — **logical modules**, not separate services today | | SFU stub | `examples/sfu/`, `api/sfu_health.php` | Post-alpha; stay in console until F1 SPEC | | Experimental / lab | Nested `.git` under `examples/` (not `third-party/` or `backend/url-shortener`) | **Out of scope** — omit from migration docs and manifests | | third-party codecs | `third-party/libvpx|opus|speex|wireguard-android` | Stay **submodules of ac-mobile** (upstream URLs unchanged); Gitea mirrors per existing migrate script | [AI comment]: **Correction for draft “how” section:** `be-console` is **not** `./examples/build_console` — that is **builder**. Primary operator console is **`examples/crash_reporter/backend`** (crashes + tickets + graphs + RBAC + remote access APIs). Builder is separate product surface under `/build/`. ────────────────────────────────────────────────────────────────────────────── B. Infrastructure & cloud fit (combine lab + prod + future cloud) ────────────────────────────────────────────────────────────────────────────── Principles (from [specs/20100612_1_scaling.md](../specs/20100612_1_scaling.md), [INFRA.md](../INFRA.md), cluster0): 1. **Deploy unit = VM role or container image**, not git repo count. Phase A prod: `be-web-1` runs nginx + PHP-FPM for hub + console + graphs UI; `be-data-1` MariaDB; `be-ops-1` url-shortener + Gitea; `be-build-1` builder. 2. **cluster0 pattern** (NFS config only, app on local disk, GTID MariaDB) maps to cloud as: - NFS `/shared/cluster/` → **ConfigMaps / object storage** for nginx + SQL seeds + scripts - Per-node `/var/www/...` → **container image** or **git pull on VM** per service - Managed DB → **connection string in secret** (PO: “pay for DB service”) — must **not** live in `ms-common` git 3. **PHP session + RBAC**: Shared cookie path `/app/androidcast_project` across hub/crashes/build ([BUILD_DEPLOY.md](../BUILD_DEPLOY.md)). Until true SSO/service tokens exist, **splitting BE UI repos is fine**; splitting **API auth** into N repos without `ac-platform-php` Composer package is painful. 4. **OpenAPI**: PO wants MS OpenAPI-compatible — today APIs are PHP files, not generated spec. Recommend **`ac-platform-openapi`** (or `ac-docs/openapi/`) as **contract-first** artifacts; implement in console first, extract services later. 5. **CI**: `build.config.yml` + CircleCI shape assume **monorepo checkout**. Meta-repo needs **per-repo pipelines** + `ac-deploy` triggering builds with `git_ref` across submodules (builder already does this for `android_cast`). 6. **URL / paths:** Under **discussion** — PO wants path-per-service (§M), not frozen `?view=` under `/crashes/`. nginx + mobile `BackendEndpoints` must migrate with redirects. [AI comment]: Shared cookie path may become `/app/androidcast_project/` at **edge** only while backends move to `/issues/`, `/tickets/`, etc. ────────────────────────────────────────────────────────────────────────────── C. Target structure — **full microservice** (PO decision 2026-06-18) ────────────────────────────────────────────────────────────────────────────── PO chose **full microservice** end-state (§K comparison). Delivery remains **phased** (§D). ```text Platform (libraries — Composer, not runtime MS) ac-platform-php, ac-platform-db, ac-platform-web, ac-scripts, ac-docs Infrastructure ac-deploy submodules ac-scripts; cluster0/docker/nginx ac-workspace optional clone manifest only (§N) — NOT unified build Clients ac-mobile-android (+ future ac-mobile-ios) ac-session-studio Microservices (OpenAPI APIs / workers) 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) 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 (optional) Edge ac-platform-edge nginx BFF — recommended for cookie + URL migration (§M) ``` [AI]: Collapse PO’s **ms-vpn-rssh** + **ms-vpn-wireguard** → **ac-ms-remote-access**. Drop **ac-ms-vcs** as code repo (Gitea = infra). Drop **ac-ms-tracker** as separate MS — split into **ac-ms-issues** + **ac-ms-tickets** (different URLs PO wants). **Risk mitigation:** Composer semver for platform libs (avoid @common submodule diamond in 20+ repos). ────────────────────────────────────────────────────────────────────────────── D. Phased migration (safe order — no big-bang) ────────────────────────────────────────────────────────────────────────────── | Phase | Action | Alpha blocker? | Rollback | |-------|--------|----------------|----------| | **P0** | Create Gitea org **`ac`**; mirror legacy → **ac-workspace** (optional) | No | Keep `android_cast` mirror | | **P1** | Extract **ac-docs**, **ac-session-studio** submodules; meta points SHAs | No | Revert submodule | | **P2** | Extract **ac-ms-url-shortener** path to `ac/ac-ms-url-shortener` (already submodule — change URL only) | No | Old URL works via mirror | | **P3** | **ac-platform-php** + **ac-platform-web** + **ac-ms-identity** first (everything depends on auth) | **Yes** for MS split | Shim monolith | | **P4** | Extract **ac-ms-issues**, **ac-ms-tickets**, **ac-ms-rbac**, **ac-ms-devices** + matching **ac-be-*** UI repos | Medium | Edge proxy to monolith | | **P5** | **ac-mobile-android**, **ac-deploy** (+ submodule **ac-scripts**), **ac-ms-build**, **ac-ms-ota** | Medium | Per-repo CI | | **P6** | **ac-platform-edge** nginx routes (§M); retire `/crashes/?view=` | Medium | 301 redirects | | **P7** | cluster0 + cloud VMs (§O); optional **ac-ms-graphs**, **ac-ms-remote-access** | No | Per scaling SPEC | [AI comment]: Do **not** start P4 until P3 — otherwise Auth/Database duplicates diverge in days. **ms-common sensitive data:** Split into: - `ac-platform-php` — code (session helpers, RBAC classes, DB adapter interfaces) - **Runtime config** — `config.php` / env / K8s secrets per deploy (never in git) - Optional `ac-platform-db` — **SQL migrations only** (shared schema), consumed by console + shortener + builder ────────────────────────────────────────────────────────────────────────────── E. The what (original table — annotated) ────────────────────────────────────────────────────────────────────────────── Current project structure Project | Placement | Repo | State | Description ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ AndroidCast all in one | repo root | git://f0xx.org/android_cast | monolithic | all-in-one project, needs to be splitted [AI]: → becomes **ac-meta** umbrella; keep **read-only mirror** at old URL ≥ 1 release libvpx | third-party/libvpx | https://chromium.googlesource.com/webm/libvpx | 3rdparty exported submodule | VPx video codecs [AI]: stays upstream URL in .gitmodules; Gitea mirror `AndroidCast/libvpx` unchanged opus | third-party/opus | https://github.com/xiph/opus | 3rdparty exported submodule | Opus voice codec speex | third-party/speex | https://github.com/xiph/speex/ | 3rdparty exported submodule | Speex voice codec wireguard | third-party/wireguard-android | https://git.zx2c4.com/wireguard-android | 3rdparty exported submodule | wireguard for android url-shortener | backend/url-shortener | git://f0xx.org/androidcast_project/url-shortener | part of AndroidCast backend | url shortener standalone backend [AI]: migrate to **git://f0xx.org/ac/ac-ms-url-shortener**; alias old URL ────────────────────────────────────────────────────────────────────────────── F. The how (original target — annotated + fixes) ────────────────────────────────────────────────────────────────────────────── Next hope project structure AndroidCast project - all in one | git://f0xx.org/ac/ac-meta |-- AndroidCast - common | @ac-platform-php [AI: Composer, not submodule diamond] |-- AndroidCast - mobile | @ac-mobile |-- AndroidCast - BE | @ac-be-console (+ builder, hub as siblings) ... TBD AndroidCast project | Placement (@ - submodule) | Description | Repo ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ AndroidCast - common | @common | project all common | git://f0xx.org/ac/ac-common [AI]: **Rename → ac-platform-php** (Composer). Reserve **ac-common** for non-PHP only: LICENSE templates, OpenAPI, semver constants — or drop repo and fold into ac-docs. |-- AndroidCast - docs | @docs | project docs, BE, MS, mobile, web, everything | git://f0xx.org/ac/ac-docs |-- AndroidCast - scripts | @scripts | common project scripts | git://f0xx.org/ac/ac-scripts [AI]: merge ac-scripts into **ac-deploy** unless mobile-only scripts dominate AndroidCast - mobile | @mobile | mobile app sources | git://f0xx.org/ac/ac-mobile |-- AndroidCast - common | @common | | git://f0xx.org/ac/ac-common [AI]: mobile should NOT submodule ac-common PHP — only third-party natives AndroidCast - Session Studio | @session-studio | offline analytic tools | git://f0xx.org/ac/ac-session-studio |-- AndroidCast - common | @common | | git://f0xx.org/ac/ac-common [AI]: session-studio has no PHP dep — drop @common edge AndroidCast - BE - MS | @backend | backend microservices common base (UI) | git://f0xx.org/ac/ac-be-microservice [AI]: **Overloaded name.** Split: **ac-be-console** (main UI+API), **ac-platform-php** (lib). “ac-be-microservice” as umbrella meta for BE apps optional. |-- AndroidCast - common | @common | | git://f0xx.org/ac/ac-common AndroidCast - MS | @microservices | microservice commons | git://f0xx.org/ac/ac-microservice [AI]: defer **ac-microservice** meta-repo until ≥3 independently deployed APIs exist (today: 1 = url-shortener) |-- AndroidCast - common | @common | | git://f0xx.org/ac/ac-common ... TBD AndroidCast BE microservices and their derivatives (OpenAPI providers, any REST API services for web and mobile apps) AndroidCast - MS - template <- AndroidCast - MS (@ means suibmodule) |git://f0xx.org/ac/ac-microservice/ac-ms-template [AI]: good template for **future** services; seed from url-shortener layout (public/, src/, sql/, tests/) | -- AndroidCast - common | @common | project all common | git://f0xx.org/ac/ac-common | -- AndroidCast - MS - common | @ms-common | microservices common | git://f0xx.org/ac/ac-microservice/ac-ms-common [AI]: **ms-common = ac-platform-php + openapi + migration runner** — NOT DB passwords. Fix typo **@ms-commmon** in remote-access row below. |-- AndroidCast - MS - builder | @ms-builder | builder microservice | git://f0xx.org/ac/ac-microservice/ac-ms-builder [AI]: today = **ac-be-builder** (UI+worker in one); split worker when be-build-1 is isolated CI agent only |-- AndroidCast - MS - VPN | @ms-vpn | VPN microservice | git://f0xx.org/ac/ac-microservice/ac-ms-vpn [AI]: **Phase 6+** — API surface = `remote_access.php` + provisioners; client stays in ac-mobile |-- AndroidCast - MS - VPN - RSSH | @ms-vpn-rssh | VPN RSSH microservice | git://f0xx.org/ac/ac-microservice/ac-ms-vpn-rssh |-- AndroidCast - MS - VPN - WireGuard | @ms-vpn-wireguard | VPN WG microservice | git://f0xx.org/ac/ac-microservice/ac-ms-vpn-wireguard [AI]: package by directory inside console first: `src/RemoteAccess/Rssh/`, `src/RemoteAccess/WireGuard/` |-- AndroidCast - MS - VCS | @ms-vcs | VCS microservice (gitea) | git://f0xx.org/ac/ac-microservice/ac-ms-vcs [AI]: **Not a code repo** — Gitea is infra; keep **ac-deploy** scripts + docs for Gitea ops |-- AndroidCast - MS - URL shortener | @ms-url-shortener | URL shortener microservice | git://f0xx.org/ac/ac-microservice/ac-ms-url-shortener [AI]: **P2** — flatten path to `git://f0xx.org/ac/ac-ms-url-shortener` (no nested ac-microservice parent) |-- AndroidCast - MS - analytics | @ms-analytics | analytics microservice | git://f0xx.org/ac/ac-microservice/ac-ms-analytics [AI]: graphs ingest + GA config — module in console until read load warrants split |-- AndroidCast - MS - orchestration | @ms-orchestration | orchestration microservice | git://f0xx.org/ac/ac-microservice/ac-ms-orchestration [AI]: today = **ac-deploy** + builder API; name collision with folder `orchestration/` |-- AndroidCast - MS - tracker | @ms-tracker | issues & tickets tracker microservice | git://f0xx.org/ac/ac-microservice/ac-ms-tracker |-- AndroidCast - MS - RBAC | @ms-rbac | RBAC microservice | git://f0xx.org/ac/ac-microservice/ac-ms-rbac ... TBD Sub-project of AndroidCast BE/MS, mostly Web UI stuff, but also should be OpenAPI-compatible and provide services to the mobile app (@ means suibmodule) AndroidCast - BE - common <- AndroidCast - BE - MS | git://f0xx.org/ac/ac-backend [AI]: prefer **per-app repos** (ac-be-console, ac-be-builder, …) over deep `ac-backend/*` tree — flatter Gitea permissions |-- AndroidCast - BE - vcs (UI) | @be-vcs | VCS frontend, former gitea, backend UI | git://f0xx.org/ac/ac-backend/ac-be-vcs [AI]: Gitea **is** the UI — link from hub only; optional thin PHP wrapper if needed |-- AndroidCast - MS - vcs | @ms-vcs | VCS microservice (gitea) | git://f0xx.org/ac/ac-microservice/ac-ms-vcs |-- AndroidCast - BE - console (UI) | @be-console | git://f0xx.org/ac/ac-backend/ac-be-console | primary console, ./examples/build_console ? check if it is [AI]: **FIX:** primary console = **ac-be-console** ← `examples/crash_reporter/backend`. Builder = **ac-be-builder** ← `examples/build_console`. |-- AndroidCast - MS - common | @ms-common | git://f0xx.org/ac/ac-microservice/ac-ms-common | microservice commons |-- AndroidCast - BE - landing (UI) | @be-landing | git://f0xx.org/ac/ac-backend/ac-be-landing | landing page(s), now in ./examples/app_hub |-- AndroidCast - MS - common | @ms-common | git://f0xx.org/ac/ac-microservice/ac-ms-common | microservice commons |-- AndroidCast - BE - issues (UI) | @be-issues | git://f0xx.org/ac/ac-backend/ac-be-issues | issues tracker UI, now is in ./examples somewhere [AI]: **same PHP app** as tickets — `?view=` routes in crash_reporter views, not separate deployable |-- AndroidCast - MS - tracker | @ms-tracker | git://f0xx.org/ac/ac-microservice/ac-ms-tracker | issues tracker microservice shared base, now is in ./examples somewhere |-- AndroidCast - BE - tickets (UI) | @be-tickets | git://f0xx.org/ac/ac-backend/ac-be-tickets | tickets UI, now is in ./examples somewhere |-- AndroidCast - MS - tracker | @ms-tracker | git://f0xx.org/ac/ac-microservice/ac-ms-tracker | issues tracker microservice shared base, now is in ./examples somewhere |-- AndroidCast - BE - graphs (UI) | @be-graphs | git://f0xx.org/ac/ac-backend/ac-be-graphs | graphs UI, now somewhere in ./examples |-- AndroidCast - MS - analytics | @ms-analytics | git://f0xx.org/ac/ac-microservice/ac-ms-analytics | analytics base microservice |-- AndroidCast - BE - analytics (UI) | @be-analytics | git://f0xx.org/ac/ac-backend/ac-be-analytics | analytics and statistics web UI |-- AndroidCast - MS - analytics | @ms-analytics | git://f0xx.org/ac/ac-microservice/ac-ms-analytics | analytics base microservice [AI]: graphs + analytics UI = views inside **ac-be-console** today (`GraphRepository`, `AnalyticsHead`) |-- AndroidCast - BE - remote access (UI) | @be-remote-access | git://f0xx.org/ac/ac-backend/ac-be-remote-access | remote access (now for vpn, somewhere in ./examples now) UI |-- AndroidCast - MS - common | @ms-commmon | git://f0xx.org/ac/ac-microservice/ac-ms-common | microservice commons [AI]: typo **commmon** → common; RA UI = admin views in console + mobile app |-- AndroidCast - MS - VPN | @ms-vpn | git://f0xx.org/ac/ac-microservice/ac-ms-vpn | VPN MS as a dependency |-- AndroidCast - MS - RBAC | @ms-rbac | @ms-rbac | git://f0xx.org/ac/ac-microservice/ac-ms-rbac | RBAC MS as a dependency |-- AndroidCast - BE - URL shortener (UI) | @be-url-shortener | git://f0xx.org/ac/ac-backend/ac-be-url-shortener | URL shortener UI, now is in separate submodule [AI]: short-link **admin UI** is in crash console (`short_links.js`, hub tokens); **API** is submodule |-- AndroidCast - MS - URL shortener | @ms-url-shortener | git://f0xx.org/ac/ac-microservice/ac-ms-url-shortener | URL shortener microservice, now is in separate submodule |-- AndroidCast - BE - builder (UI) | @be-builder | git://f0xx.org/ac/ac-backend/ac-be-builder | orchestration builder UI, now in ./orchestration [AI]: **FIX:** builder UI = `examples/build_console`; **orchestration/** = docker/cluster0 (**ac-deploy**) |-- AndroidCast - MS - orchestration | @ms-orchestration | git://f0xx.org/ac/ac-microservice/ac-ms-orchestration | orchestration microservice, now in ./orchestration |-- AndroidCast - BE - RBAC (UI) | @be-rbac | git://f0xx.org/ac/ac-backend/ac-be-rbac | RBAC backend, now mixed within ./examples somewhere |-- AndroidCast - MS - common | @ms-common | git://f0xx.org/ac/ac-microservice/ac-ms-common | microservice commons |-- AndroidCast - MS - RBAC | @ms-rbac | git://f0xx.org/ac/ac-microservice/ac-ms-rbac | RBAC microservice |-- AndroidCast - BE - OTA | @be-ota | git://f0xx.org/ac/ac-backend/ac-be-ota | OTA BE UI |-- AndroidCast - MS - OTA | @ms-ota | git://f0xx.org/ac/ac-microservice/ac-ms-ota | OTA microservice, now intermixed in examples/ota and other commons [AI]: OTA = static tree + builder publish + nginx location; extract API when `5.1 OTA` nginx stable ... TBD ms-common (microservices common) needs a sharp eye, it may share project sensitive parts, like common stuff such as shared web sessions, DB access (or should be separated to @be-db-service/@ac-db-service sort of) [AI]: **Agree.** Recommended split: - **ac-platform-php** — session *code*, Auth, Rbac, PDO factory (reads DSN from env) - **ac-platform-db** — SQL migrations + schema version table (shared by console, builder, shortener) - **ac-deploy/secrets** — example only; prod DSN in vault / Alpine `config.php` outside git - **No ac-db-service runtime** until you run DB proxy (PlanetScale, RDS, etc.) — app VMs use driver + secret ────────────────────────────────────────────────────────────────────────────── G. FULL REPO CATALOG — microservice end-state (Gitea org **ac**) ────────────────────────────────────────────────────────────────────────────── Canonical clone: `git://f0xx.org/ac/`. HTTPS UI: `https://apps.f0xx.org/app/androidcast_project/git/ac/.git` (path TBD with edge migration). Legacy `git://f0xx.org/android_cast` → read-only mirror until retired. | ID | Repo | Git URL | Role | From (monolith) | VM / cloud slot | |----|------|---------|------|-----------------|-----------------| | **Workspace** | | W0 | ac-workspace | `git://f0xx.org/ac/ac-workspace` | Optional submodule manifest; **no unified build** | `.gitmodules` | dev laptops | | **Platform** | | P0 | ac-platform-php | `git://f0xx.org/ac/ac-platform-php` | Composer: HTTP, auth client, PDO factory | Auth*, bootstrap | baked into PHP images | | P1 | ac-platform-db | `git://f0xx.org/ac/ac-platform-db` | SQL migrations + schema version | sql/, migrations | be-data-1 job | | P2 | ac-platform-web | `git://f0xx.org/ac/ac-platform-web` | Shared CSS/JS/theme | crashes/assets, hub links | CDN / edge static | | P3 | ac-platform-edge | `git://f0xx.org/ac/ac-platform-edge` | nginx routes, cookie domain, proxy | fe/apps.conf | be-web-1 / FE | | P4 | ac-scripts | `git://f0xx.org/ac/ac-scripts` | CI, OTA, native codec, pdf scripts | `scripts/` | CI runners | | P5 | ac-docs | `git://f0xx.org/ac/ac-docs` | Documentation | `docs/` | — | | **Deploy** | | D0 | ac-deploy | `git://f0xx.org/ac/ac-deploy` | docker, cluster0, env templates; **uses ac-scripts** | `orchestration/` | all VMs | | **Clients** | | C0 | ac-mobile-android | `git://f0xx.org/ac/ac-mobile-android` | Android app + ndk + third-party | `app/`, `ndk/` | CI → OTA | | C1 | ac-mobile-ios | `git://f0xx.org/ac/ac-mobile-ios` | Future iOS client | — | CI → OTA | | C2 | ac-session-studio | `git://f0xx.org/ac/ac-session-studio` | Desktop analyzer | `desktop/session-studio/` | releases | | **Microservices** | | S0 | ac-ms-template | `git://f0xx.org/ac/ac-ms-template` | Cookiecutter for new PHP MS | url-shortener layout | — | | S1 | ac-ms-identity | `git://f0xx.org/ac/ac-ms-identity` | Users, login, register, 2FA, sessions | Auth*, UserRepository | be-web-1 | | S2 | ac-ms-rbac | `git://f0xx.org/ac/ac-ms-rbac` | Companies, memberships, privileges | Rbac*, RbacAdmin* | be-web-1 | | S3 | ac-ms-devices | `git://f0xx.org/ac/ac-ms-devices` | Device registry | DeviceRepository | be-web-1 | | S4 | ac-ms-issues | `git://f0xx.org/ac/ac-ms-issues` | Crash/report ingest + reports API | upload, Report*, Tag* | be-web-1 | | S5 | ac-ms-tickets | `git://f0xx.org/ac/ac-ms-tickets` | Tickets workflow, comments, attachments | Ticket* | be-web-1 | | S6 | ac-ms-graphs | `git://f0xx.org/ac/ac-ms-graphs` | Graph ingest + query | GraphRepository, graph_*.php | be-web-1 | | S7 | ac-ms-remote-access | `git://f0xx.org/ac/ac-ms-remote-access` | WG + RSSH control API | RemoteAccess*, WireGuard*, Rssh* | be-ops-1 | | S8 | ac-ms-url-shortener | `git://f0xx.org/ac/ac-ms-url-shortener` | Short link API | `backend/url-shortener/` | be-ops-1 | | S9 | ac-ms-build | `git://f0xx.org/ac/ac-ms-build` | Build queue + worker API | BuildRunner, build_console APIs | be-build-1 | | S10 | ac-ms-ota | `git://f0xx.org/ac/ac-ms-ota` | Channel manifests; multi-client SHAs | OTA scripts + v0 tree | be-web-1 / OBJ | | S11 | ac-ms-notifications | `git://f0xx.org/ac/ac-ms-notifications` | SMTP / auth mail (post-alpha) | AuthMailer | be-ops-1 | | **Backend UI** | | B0 | ac-be-hub | `git://f0xx.org/ac/ac-be-hub` | Landing | `examples/app_hub/` | be-web-1 | | B1 | ac-be-issues | `git://f0xx.org/ac/ac-be-issues` | Issues UI → S4 | views reports/* | be-web-1 | | B2 | ac-be-tickets | `git://f0xx.org/ac/ac-be-tickets` | Tickets UI → S5 | views tickets/* | be-web-1 | | B3 | ac-be-graphs | `git://f0xx.org/ac/ac-be-graphs` | Graphs dashboard UI | graphs views | be-web-1 | | B4 | ac-be-remote-access | `git://f0xx.org/ac/ac-be-remote-access` | RA admin UI → S7 | view remote_access | be-web-1 | | B5 | ac-be-access | `git://f0xx.org/ac/ac-be-access` | RBAC admin UI → S2 | view rbac | be-web-1 | | B6 | ac-be-builder | `git://f0xx.org/ac/ac-be-builder` | Builder UI → S9 | `examples/build_console/` | be-build-1 | | B7 | ac-be-auth | `git://f0xx.org/ac/ac-be-auth` | Login/register chrome → S1 | login.php shared | be-web-1 | | **Third-party (submodules of C0 only)** | | — | libvpx, opus, speex, wireguard-android | upstream URLs + Gitea mirrors under `ac/` | Native deps | `third-party/*` | mobile CI | | **Future** | | F1 | ac-ms-sfu-signaling | `git://f0xx.org/ac/ac-ms-sfu-signaling` | WebRTC signaling | examples/sfu | be-media-N | | F2 | ac-ms-media-transcode | `git://f0xx.org/ac/ac-ms-media-transcode` | VOD/ffmpeg | V.2x draft | be-media-N | **PO draft mapping fixes:** - `ac-be-console` (monolith) → **dissolved** into B1–B5 + S4–S7 - `ac-ms-tracker` → **S4 + S5** (issues ≠ tickets — PO URL split confirms) - `ac-ms-analytics` → **S6** (graphs) + later BI; GA config in **P2 platform-web** - `ac-ms-orchestration` → **S9 + D0** (worker vs deploy) - `ac-ms-vcs` → **not a repo**; document in **D0** - `ac-be-url-shortener` UI → admin panel in **B5** or **B0** calling **S8** (tokens already in crashes console) **ac-deploy ↔ ac-scripts:** D0 submodules P4 at pinned SHA; deploy-local scripts only for image entrypoints. ────────────────────────────────────────────────────────────────────────────── H. ac-workspace sketch (optional — PO §5) ────────────────────────────────────────────────────────────────────────────── **Purpose:** “I only work on mobile” or “I only work on tickets UI” — clone workspace, init selected submodules. **Not** for building everything in one Gradle/PHP tree. ```ini # ac-workspace — example partial checkout [submodule "mobile-android"] path = clients/android url = git://f0xx.org/ac/ac-mobile-android [submodule "ms-issues"] path = services/issues url = git://f0xx.org/ac/ac-ms-issues [submodule "be-issues"] path = ui/issues url = git://f0xx.org/ac/ac-be-issues [submodule "deploy"] path = deploy url = git://f0xx.org/ac/ac-deploy ``` Developers without workspace clone individual repos directly. ────────────────────────────────────────────────────────────────────────────── I. PO decisions (2026-06-18) — recorded ────────────────────────────────────────────────────────────────────────────── | # | Question | Decision | |---|----------|----------| | 1 | Gitea org | **`ac`** | | 2 | Architecture | **Full microservice** end-state (phased delivery) — §K | | 3 | ac-scripts | **Separate repo**; **ac-deploy submodules/invokes it** | | 4 | Public URLs | **Change desired** — path-per-service (§M); not frozen under `/crashes/?view=` | | 5 | Meta repo | **`ac-workspace` optional** — selective clone only; **not** build-all-in-one; §N OTA | | 6 | Cloud | **No K8s requirement** — start VM lift-and-shift (§O); K8s later optional | ────────────────────────────────────────────────────────────────────────────── J. Microservice vs modular monolith — comparison (PO requested) ────────────────────────────────────────────────────────────────────────────── | Criterion | Full microservice (PO choice) | Modular monolith (single ac-be-console) | |-----------|------------------------------|----------------------------------------| | **Independent deploy** | Deploy tickets without touching issues | One PHP deploy for any UI fix | | **Team scaling** | Different owners per repo/service | Single codebase, simpler grep | | **Failure isolation** | Ticket MS down ≠ crash ingest | Shared FPM pool — blast radius larger | | **CI speed** | Small repos, faster per-service tests | One `./gradlew`-scale PHP test suite | | **Auth/session** | Needs **ac-ms-identity** + edge cookie early | Already works (`ac_crash_sess`) | | **DB** | Shared MariaDB OK initially; schema ownership per MS | One migration stream today | | **Operational cost** | More nginx routes, more images, more logs | One BE tree to sync ([INFRA.md](../INFRA.md)) | | **PO microservice learning curve** | Higher — mitigated by **ac-ms-template**, **D0** | Lower short-term | | **Cloud path** | Maps 1:1 to VM roles then containers | Lift whole monolith first | | **URL clarity** | Natural `/issues/`, `/tickets/` per service | Stuck on `?view=` without refactor | | **Rollback** | Revert one service SHA | Revert one monolith commit | | **Risk for alpha** | **Higher** if done before identity split | Lower — current prod pattern | [AI]: PO choice is valid **if P3 (identity + platform) is non-negotiable first**. Without it, full MS split repeats the build-console/bootstrap.php class of failures across N repos. ────────────────────────────────────────────────────────────────────────────── K. Service dependency graph (logical + structural + repo) ────────────────────────────────────────────────────────────────────────────── ```mermaid flowchart TB subgraph clients [Clients] AND[ac-mobile-android] IOS[ac-mobile-ios future] HUB[ac-be-hub] SS[ac-session-studio] end subgraph edge [Edge] EDGE[ac-platform-edge] end subgraph core [Core platform MS] 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 subgraph ui [Backend UI] UI_I[ac-be-issues] UI_T[ac-be-tickets] UI_G[ac-be-graphs] UI_R[ac-be-remote-access] UI_A[ac-be-access] UI_B[ac-be-builder] end AND -->|upload API| EDGE AND -->|RA API| EDGE AND -->|graph upload| EDGE HUB --> EDGE UI_I & UI_T & UI_G & UI_R & UI_A & UI_B --> EDGE EDGE --> ID & IS & TK & GR & RA & UL & BL & OT & RB ID --> RB RB --> DV IS --> DV IS --> RB TK --> RB TK -.->|optional link| IS GR --> ID RA --> RB RA --> DV RA -.->|issue deep links| IS BL --> ID BL -->|git clone| GITEA[(Gitea infra)] OT --> BL OT --> AND OT --> IOS UL --> RB ``` **Dependency rules (enforce in DR/SPEC):** | Service | Hard depends on | Soft / read depends on | Mobile / public API | |---------|-----------------|------------------------|---------------------| | ac-ms-identity | ac-platform-db (users schema) | ac-ms-notifications (mail) | register, login | | ac-ms-rbac | identity (JWT/session validation) | — | — | | ac-ms-devices | rbac (company scope) | identity | — | | ac-ms-issues | devices, rbac | tags catalog | **upload.php** | | ac-ms-tickets | rbac | issues (link ticket↔report) | — | | ac-ms-graphs | identity | — | graph_upload | | ac-ms-remote-access | rbac, devices | issues (device context URLs) | remote_access.php | | ac-ms-url-shortener | rbac (API tokens) | — | s.f0xx.org | | ac-ms-build | identity | gitea mirror | — | | ac-ms-ota | build artifacts | mobile/ios SHAs | `/v0/ota/` | | ac-be-hub | identity (session for nav) | **P2 platform-web** assets | — | **Cross-cutting fixes vs PO draft:** 1. **Auth must be first MS** — every UI and API currently includes `bootstrap.php` → Auth. 2. **Devices before issues** — upload auto-registers device + company ([README](../examples/crash_reporter/backend/README.md) RBAC). 3. **Hub → crashes assets** — today `app_hub/index.php` loads `/crashes/assets/css/app.css`; extract **ac-platform-web** before splitting hub. 4. **Builder → same DB users** — build_console uses `androidcast_crashes.users`; cannot split S9 before S1. 5. **Short links admin** — UI in monolith, API in submodule; UI calls S8, not duplicate repo **ac-be-url-shortener**. 6. **Graphs** — already separate nginx location `/graphs/` ([apps.conf](../../examples/crash_reporter/backend/nginx/fe/apps.conf)) — good MS boundary. **Suggested new intermediates (actors):** | Service | Why | |---------|-----| | **ac-ms-identity** | Single login/register/2FA; avoids 8 copies of Auth.php | | **ac-ms-devices** | Shared by issues, RA, graphs device keys | | **ac-platform-edge** | One nginx config for PO’s URL map + SSO cookie | | **ac-ms-ota** | PO multi-repo Android+iOS same version (§N) | | **ac-ms-notifications** | Decouple SMTP from identity (task 2.x mail frozen) | | **ac-ms-attachments** (later) | Ticket files → object store when > local disk | ────────────────────────────────────────────────────────────────────────────── L. Public URL migration map (PO §4) ────────────────────────────────────────────────────────────────────────────── Base prefix (discussion): keep **`/app/androidcast_project/`** for alpha compatibility, or shorten to **`/app/ac/`** later. Below uses PO’s intent under current prefix. | Today | Target path | MS / UI | Notes | |-------|-------------|---------|-------| | `/crashes/?view=reports` | **`/issues/`** | B1 → S4 | “Issue tracker” / crash reports list | | `/crashes/?view=report&id=N` | **`/issues/N`** or `/issues/report/N` | B1 | Detail | | `/crashes/?view=tickets` | **`/tickets/`** | B2 → S5 | Tickets catalog | | `/crashes/?view=ticket&id=N` | **`/tickets/N`** | B2 | Detail | | `/crashes/?view=rbac` | **`/access/`** | B5 → S2 | RBAC admin | | `/crashes/?view=remote_access` | **`/remote-access/`** | B4 → S7 | RA admin | | `/crashes/?view=short_links` | **`/short-links/`** or hub panel | B0/B5 → S8 | API stays on s.f0xx.org | | `/crashes/?view=home` | **`/`** hub or `/console/` | B0 | Retire crashes “home” | | `/crashes/api/upload.php` | **`/issues/api/upload`** or `/api/v1/issues/upload` | S4 | Update `BackendEndpoints.java`, `CrashSettings.java` | | `/crashes/api/*` (tickets) | **`/tickets/api/*`** | S5 | | | `/graphs/` | **`/graphs/`** (keep) | B3 → S6 | Already separate vhost block | | `/build/` | **`/build/`** (keep) | B6 → S9 | | | `/` (hub) | **`/`** (keep) | B0 | | | `/git/` | **`/git/`** (keep) | Gitea | Not a MS | | `/v0/ota/` | **`/v0/ota/`** (keep) | S10 | | **Migration mechanics:** ac-platform-edge 301 redirects old URLs ≥ 1 release; mobile app legacy URL rewrite already in `BackendEndpoints.normalizeUploadUrl()`. **Naming note:** Today “reports” in code = **issues/crashes** in product language — align UI strings when moving to `/issues/`. ────────────────────────────────────────────────────────────────────────────── M. ac-workspace + OTA multi-repo versioning (PO §5) ────────────────────────────────────────────────────────────────────────────── **ac-workspace is NOT:** - A single Gradle/Composer build root - Required for CI (each repo has own pipeline) **ac-workspace IS:** - Optional manifest: “which repos at which SHA for a release train” - Convenience for developers who want `clients/android` + `services/issues` side by side **OTA same version, different client SHAs (Android + iOS):** `ac-ms-ota` channel manifest example: ```json { "channel": "staging", "version": "00.02.00.00", "artifacts": { "android": { "repo": "ac-mobile-android", "git_sha": "abc123", "apk_url": "..." }, "ios": { "repo": "ac-mobile-ios", "git_sha": "def456", "ipa_url": "..." } } } ``` Builder (S9) triggers per-repo builds; **S10** assembles manifest. Mobile apps read **`version`** for UX; **`git_sha`** per platform for support. ────────────────────────────────────────────────────────────────────────────── N. Cloud & VM strategy (PO §6 — no K8s experience) ────────────────────────────────────────────────────────────────────────────── **Recommendation: Phase 1 = VM lift-and-shift** (matches cluster0 lab, scaling SPEC §6.3, PO skill set). | Stage | Where | Pattern | |-------|-------|---------| | **Now** | FE + BE Alpine | nginx + PHP-FPM + MariaDB ([INFRA.md](../INFRA.md)) | | **Lab** | cast01–03 | GTID MariaDB, NFS config only, apps local ([cluster0 ARCHITECTURE](../../orchestration/sim/cluster0/ARCHITECTURE.md)) | | **Cloud phase A** | 4–6 VMs (be-web, be-data, be-ops, be-build) | Same as scaling table; **docker only on build** | | **Cloud phase B** | Managed DB (RDS-class) | Apps use DSN secret; **ac-platform-db** migrations as job | | **Cloud phase C** (optional) | K8s / compose swarm | **Not required** — introduce when MS count > ~8 and PO wants auto-scale | **ac-deploy deliverables for cloud:** Terraform optional; minimum **Ansible + docker-compose fragments per VM role** + env templates. Each MS = one PHP-FPM pool or one container behind edge nginx. **Inter-service calls (PO poor on microservices):** Start with **HTTP on localhost/private VLAN** (same BE host), not service mesh. Edge nginx routes public paths; internal `127.0.0.1:900x` or docker network. OpenAPI spec in **ac-docs/openapi/** is the contract. ────────────────────────────────────────────────────────────────────────────── O. DR readiness checklist ────────────────────────────────────────────────────────────────────────────── - [x] Map monolith → full MS catalog (§G) - [x] PO decisions recorded (§I) - [x] Comparison table (§J) - [x] Dependency graph + fixes (§K) - [x] URL migration map (§L) - [x] Workspace / OTA model (§M) - [x] Cloud recommendation (§N) - [ ] PO confirms URL prefix (`/app/androidcast_project/` vs `/app/ac/`) — **locked: full prefix** - [ ] PO confirms **ac-ms-identity** as P3 gate — **approved** - [x] Write `docs/DRs/20260618_repos_reorganizing.md` + PDF - [ ] Update gitea migrate scripts for org **`ac`** - [ ] Migration runbook P0–P7 [AI]: **Create Gitea repos from §G table in waves:** Wave 1 = P4,P5,D0,C2,S8; Wave 2 = S1,S2,S3; Wave 3 = S4,S5 + B1,B2; then edge + URL migration.