16 KiB
02 — Repository & Infrastructure Map
Surface: whole repo Source of truth for: layout, workspaces, build/test commands, CI/CD, Docker, deploy, scripts, resources
1. Repository layout
D:/workspace/D3ROVoice
├── apps/
│ ├── desktop/ Electron app (npm workspace @d3ro/desktop)
│ ├── web/ Next.js console (npm workspace @d3ro/web)
│ ├── admin/ Next.js back office (npm workspace @d3ro/admin)
│ ├── mobile-rn/ React Native product mobile app (NOT an npm workspace)
│ ├── api-server/ ASP.NET Core 10 API (D3ROVoice.Api)
│ ├── api-server.Tests/ xUnit tests for the API
│ └── admin-swagger/ Static Swagger UI + openapi.json
├── packages/ Shared TS packages (npm workspaces)
│ ├── core/ @d3ro/core — types, errors, IPC channels, crypto, utils
│ ├── ui/ @d3ro/ui — web/desktop design system (MUI + tokens)
│ ├── ui-native/ @d3ro/ui-native — React Native design system
│ ├── i18n/ @d3ro/i18n — 12 locales, provider, formatters
│ └── api-client/ @d3ro/api-client — Supabase wrapper + shared types
├── server/
│ ├── supabase/ Supabase project: config.toml, migrations/, functions/, tests/
│ └── cloudflare-worker/ Edge gateway (wrangler.toml + src/index.ts)
├── site/ Vite landing site (deployed to Cloudflare Pages + GitHub Pages)
├── resources/ icons/ (empty), sox/ (bundled Windows SoX binaries)
├── release/ Version identity SSOT + license/evidence public keys
├── scripts/ ~145 automation scripts + scripts/ci/ (31) + scripts/lib/
├── docs/ Design, phases, v2/v3 plans, deployment, map/ (this map)
├── memory/ Project status, handoffs, archive
├── tests/e2e/, test-results/ Root-level e2e + last-run artifacts
├── scratch/ Large local evidence (APKs, screenshots, DBs) — not build input
├── supabase/ Empty scaffolding (.branches/, snippets/) — real project is server/supabase
├── .github/workflows/ GitHub Actions (6)
├── .gitlab-ci.yml GitLab CI (primary desktop/mobile release pipeline)
├── .forgejo/workflows/ Forgejo Actions (site deploy to Cloudflare Pages)
├── docker-compose.yml, docker-compose.nas.yml
├── Dockerfile.admin, apps/api-server/Dockerfile, apps/admin/Dockerfile
├── turbo.json, tsconfig.json, tsconfig.base.json, pnpm-workspace.yaml
├── package.json monorepo root, npm workspaces
├── CLAUDE.md Claude-specific project rules
└── AGENTS.md Cross-agent entry: rules + map obligation (this map's anchor)
Note: root package.json declares npm workspaces apps/desktop, apps/web, apps/admin, packages/*. pnpm-workspace.yaml also exists (apps/*, packages/*) but npm is the active toolchain. Mobile is intentionally outside the workspace.
2. Toolchain & versions
| Tool | Version | Source |
|---|---|---|
| Node | 24.19.0 | .nvmrc |
| TypeScript | 5.7 | root package.json |
| .NET SDK | 10.0.300 (rollForward latestPatch) | global.json |
| Deno | 2.8.1 | CI (edge-functions-quality) |
| JDK | 17 | mobile CI |
| Electron | 33.4.11 | apps/desktop/electron-builder.yml |
| React Native | 0.85 | apps/mobile-rn/package.json |
| Turborepo | turbo.json tasks: build/typecheck/test/lint/dev | turbo.json |
3. Root scripts (package.json)
npm run dev # desktop dev (electron-vite)
npm run build # desktop production build
npm run build:admin # admin production build
npm run build:all | npm run ci # scripts/ci/build-all.mjs
npm run checksum # scripts/ci/generate-checksums.mjs
npm run version:check | version:sync
npm run release:metadata[:test]
npm run release:forgejo[:check] # canonical Forgejo publisher/feed
npm run release:tag # annotated/signed immutable release tag
npm run security:secrets[:test] # hardcoded-secret scanner
npm run test:e2e:red # content-report red e2e
npm run release:mobile:boundary[:test]
npm run release:mobile:config[:test]
npm run release:mobile:build-config:test
npm run release:play:assets[:test]
npm run typecheck # all workspaces
npm run test # all workspaces
npm run lint # eslint apps/desktop apps/web apps/admin packages
npm run format # prettier
npm run typecheck:mobile # apps/mobile-rn tsc (outside npm workspaces)
npm run lint:mobile # apps/mobile-rn eslint --max-warnings=0
npm run test:mobile # apps/mobile-rn jest
npm run verify:all # aggregate: workspaces + mobile (typecheck/lint/test)
Per-app commands that matter:
| App | Commands |
|---|---|
| desktop | npm run dev --workspace=@d3ro/desktop, build, typecheck, test (vitest), playwright e2e; local STT engine: npm --prefix apps/desktop run sidecar:setup then sidecar:build (PyInstaller → sidecar-dist/sidecar), full local Windows package: npm --prefix apps/desktop run dist:win:full; setup:sox re-downloads the bundled SoX |
| mobile-rn | npm run typecheck:mobile / lint:mobile / test:mobile (root), or npm --prefix apps/mobile-rn run lint/typecheck/test; android gradle builds, Maestro E2E |
| api-server | dotnet build, dotnet test (also apps/api-server.Tests) |
| web | next build, playwright e2e in apps/web/e2e |
| admin | next build (build:admin) |
Desktop GUI execution rule (from CLAUDE.md / .agents/rules/): run via run-desktop.bat or an external terminal; do not background-launch GUI from an agent subshell.
4. Shared packages
See 03-shared-packages.md. Summary:
| Package | Provides |
|---|---|
@d3ro/core |
Domain types, D3ROError/ErrorCode, IPC channel SSOT, constants, crypto-license, pii-redactor, secure-memory, supabase-config, meeting-markdown, markdown-to-docx |
@d3ro/ui |
Theme tokens, CSS vars, MUI DS components (web/desktop) |
@d3ro/ui-native |
RN design system (MetalCard, PhosphorText, Led, PhysicalButton, WaveBars, …) |
@d3ro/i18n |
12 locales, I18nProvider, t(), date/number/relative formatters |
@d3ro/api-client |
Supabase browser/server clients, meetings/history/usage/transcribe wrappers, shared types; has vitest tests |
5. CI/CD
GitHub Actions (.github/workflows/)
| Workflow | Purpose |
|---|---|
ci.yml |
Main CI: code-quality (secret scan, mobile release/config/build-config self-tests, Play asset contract, lint, typecheck), api-server-tests, edge-functions-quality (Deno), test-matrix (win/mac/ubuntu vitest), build-validation (desktop win, admin ubuntu), mobile-android (debug/CSPRNG/E2E APKs + verifiers), mobile-emulator-e2e (API 35 + Maestro 2.7.0) |
release.yml |
On tag v*.*.*: preflight → package-windows (NSIS) → package-macos (DMG/ZIP arm64) → package-android (signed APK/AAB + evidence) → package-admin-docker (GHCR) → publish-release (checksums + GitHub Release + Forgejo canonical publish) |
deploy-site.yml |
On site/**: build Vite site, boundary self-test, deploy GitHub Pages |
build-mac.yml |
Manual macOS build (arm64/x64), sox + PyInstaller sidecar + electron-rebuild |
payple-renew.yml |
Daily cron → payple-renew edge function |
release-signing-ca.yml |
Manual Windows (Azure Trusted Signing) / macOS notarize build+sign |
GitLab CI (.gitlab-ci.yml)
Stages validate → test → build → e2e → package → publish → deploy. Primary pipeline for desktop Windows/macOS releases (Forgejo Generic Registry is the canonical updater feed; GitLab project 1172 is a legacy mirror) and production mobile releases (mobile-production-release, manual/protected). Admin NAS deploy job is intentionally disabled. package-windows/package-macos build the faster-whisper sidecar (sidecar:setup → sidecar:build) and run scripts/ci/verify-sidecar-bundle.mjs before electron-builder, so a release can never ship without the local STT engine.
Forgejo Actions (.forgejo/workflows/)
portable.yml — 태그/수동 실행으로 서명 없이 portable 채널(95MiB 7z 분할 볼륨 + Scoop 매니페스트 + 설치 스크립트)을 게시한다. WIN_CSC_* 불필요, updater feed는 건드리지 않는다.
deploy-site.yml / deploy-site-windows.yml — build site, write release identity, deploy to Cloudflare Pages d3ro (d3ro.chanpaca.net), verify live commit/version, app-links, legal URLs.
release.yml — tag-triggered Windows build (signed) + publish-forgejo-release.mjs to the canonical Forgejo feed/release hub.
6. Docker & deployment
| File | Purpose |
|---|---|
Dockerfile.admin |
3-stage Next.js admin build (node 24.19.0-alpine, port 3001) |
apps/admin/Dockerfile |
Next.js standalone runner for .next/standalone |
apps/api-server/Dockerfile |
Multi-stage .NET 10 (sdk → aspnet runtime), port 5000, VOLUME /app/data |
docker-compose.yml |
Dev/self-host: d3ro-api-server (5050→5000, ./data volume), d3ro-admin (3001), optional ollama (profile ai, 11434) |
docker-compose.nas.yml |
NAS: prebuilt d3ro-voice-api:latest + d3ro-voice-admin:latest; API mounts /volume1/docker/d3ro/wwwroot/{privacy,terms,delete-account,legal.css} read-only |
Deploy scripts: scripts/deploy-nas.ps1, scripts/deploy-nas.sh, scripts/deploy-site-to-nas.js, scripts/nas-control.sh (start/stop/restart/status/logs/backup/update).
Public endpoints (production): https://d3ro.chanpaca.net (portal/API), https://admin.chanpaca.net (admin CRM). Edge: server/cloudflare-worker proxying to the NAS origin, plus a Cron Trigger (* * * * *) that drains the Supabase push outbox via send-push?mode=drain (src/push-drain.ts; needs SUPABASE_URL var + SUPABASE_SERVICE_ROLE_KEY secret). Tunnel: Cloudflare Tunnel kd-nas.
7. server/supabase (backend)
config.toml— projectd3ro-voice, ports 55321-55324, DB major 17, auth redirects (localhost,d3ro.chanpaca.net,d3ro-voice://auth-callback), providers Google/GitHub/Apple.migrations/— 63 SQL migrations (schema, RLS, auth triggers, storage, team invites, knowledge/pgvector, push outbox, Payple/Stripe billing, admin roles, mobile platform/monetization, atomic command reorder, device revocation, content reporting, audit log, meeting documents, STT quota reservations, ad reward replay protection, team activity feed).functions/— ~27 Deno Edge Functions (stt-proxy,llm-proxy,content-report,generate-meeting-document,embed-chunks,search-knowledge,realtime-token,team-invite,team-accept,send-push,account-delete,admin-users,admin-subscriptions,admin-payments,admin-audit-log, billingbilling-catalog/stripe-checkout/stripe-portal/stripe-webhook/payple-checkout/payple-manage/payple-renew/payple-webhook,iap-verify,admob-ssv,google-play-rtdn). Shared contracts infunctions/_shared/— push transports now includewebpush.ts(VAPID + RFC 8291) andapns.ts(.p8 token) alongside FCM. CI (edge-functions-quality) runsdeno check+deno testand also the Cloudflare worker drain test.tests/— integration/E2E for content report, mobile platform/recording/reward-race, payments, mobile release preflight, push, team push security, STT quota.
Full detail: 09-supabase-backend.md.
8. scripts/ groups
- CI (
scripts/ci/, 33 files): build/version/release (build-all,sync-version,generate-checksums,verify-release-metadata,create-release-tag,extract-release-notes), security (check-no-hardcoded-secrets), mobile release gates (verify-mobile-release-boundary/-config/-build-config,verify-android-artifact/-app-links,verify-play-store-assets,prepare-whisper-model,create-mobile-release-evidence,prepare-mobile-release-publication, emulator/CSPRNG gates), keys (create-desktop-license-keypair,create-release-evidence-key, etc.), publish (publish-forgejo-releasecanonical,publish-gitlab-releasemirror; legacysync-and-publish-forgejo-release,upload-asset-to-forgejo-release), env/tooling (bootstrap-linux-toolchain.sh,audit-nas-stt-config.ps1, mobile local E2E scripts). - Deploy/release:
deploy-nas.ps1/.sh,deploy-site-to-nas.js,nas-control.sh,publish-gh.ps1,gen-keystore.js. - GCP/Google OAuth automation + inspection (~70
*.mjs):auto-configure-oauth,automate-google-oauth,setup-consent,create-*-client,check-*,inspect-*— mostly one-off/browser-driven console automation. - AdMob console automation:
admob-probe.mjs(read-only login/app/ad-unit probe),admob-login.mjs+run-admob-login.bat(one interactive headful Chrome login into a persistent profile),admob-automate.mjs(dry-run by default;--applycreates/verifies banner+rewarded units and reports Play-store link). Usesplaywrightwithchannel: 'chrome'and the gitignored.chrome-playwright-profile. - E2E / verification:
e2e-desktop-*.js,real-app-multi-tab-e2e.js,test-and-capture-all-10-ad-services.js,verify-live-production-d3ro.js. - Screenshots/captures:
capture-*.js. - Forgejo ops:
check-forgejo-actions-runs.js,capture-forgejo-*.js.
scripts/is large and partially scratch. Preferscripts/ci/*for anything release-gated, andserver/supabase/testsfor backend integration.
9. Release & versioning SSOT
| File | Purpose |
|---|---|
release/product-version.json |
version 1.3.6, androidVersionCode/iosBuildNumber 1031006, releaseDate, desktop license keyId |
release/android-release-identity.json |
package com.d3ro.voice, Play app ID, app-signing SHA-256, upload cert SHA-256, evidence keyId, AdMob unit IDs |
release/desktop-license-public.pem |
Ed25519 public key for desktop offline licenses |
release/mobile-release-evidence-public.pem |
Ed25519 public key for mobile release evidence |
apps/desktop/electron-builder.yml |
appId com.d3ro.voice, NSIS x64 (forced code signing), macOS DMG/ZIP arm64, generic Forgejo publish feed, asarUnpack native modules + @ffmpeg-installer, extraResources (icons, sounds, sox, sidecar, ffmpeg, ollama) |
apps/desktop/src/main/update-feed.ts |
Auto-update feed SSOT (canonical Forgejo + legacy GitLab mirror, channels) |
release/update-policy.json |
Update policy SSOT (channels, minimum supported version, forced update, delta/full, staged rollout, kill switch) |
apps/desktop/src/main/update-policy.ts |
Policy parsing/decision logic |
scripts/ci/publish-forgejo-release.mjs |
Canonical Forgejo registry + Release + feed publisher |
Version sync is enforced by scripts/ci/sync-version.mjs and verify-release-metadata.mjs; npm run version:check should be clean.
10. Resources & tests
resources/sox/— bundled Windows SoX (sox.exe+ DLLs) for audio capture.resources/ffmpeg/— optional bundled ffmpeg (CI or manual);getFfmpegPath()also resolves the@ffmpeg-installer/ffmpegbinary fromapp.asar.unpacked.apps/desktop/sidecar-dist/— PyInstaller sidecar bundle consumed byextraResources(gitignored; built bynpm --prefix apps/desktop run sidecar:build).resources/icons/— empty; electron-builder falls back tobuild/icon.ico|png.- Desktop tests:
apps/desktop/tests/(vitest unit + playwright e2e),apps/desktop/test-results/. - Mobile tests:
apps/mobile-rn/__tests__/(57 suites / 353 tests per mobile SSOT),.maestro/+.maestro-output/E2E evidence. Note: a full parallel Jest run can hit the 5s render timeout on slow machines; re-run the failing spec in isolation before treating it as a regression. - Web tests:
apps/web/e2e/(playwright). - API tests:
apps/api-server.Tests/(xUnit). - Root:
tests/e2e/,test-results/.last-run.json.
11. Known infrastructure gaps
See 11-gap-backlog.md for the maintained list (INFRA-*). Headlines:
apps/mobile-rnis not an npm workspace member; usetypecheck:mobile/lint:mobile/test:mobileorverify:all.- Admin NAS deploy job disabled in GitLab CI; admin ships via GitHub/GHCR + manual NAS compose.
- Two identity systems (.NET JWT/SQLite vs Supabase); a canonical resolver now exists in
@d3ro/core/entitlementbut web/mobile/.NET adoption is incremental (11GAP-ID-02).