From 941a44daacfe7a47fae34c387c9d837f3abd1ca8 Mon Sep 17 00:00:00 2001 From: YanzheL Date: Sun, 29 Mar 2026 21:01:42 +0800 Subject: [PATCH 1/2] docs: add hierarchical AGENTS knowledge base Capture repo-specific guidance at the root, backend, frontend, migrations, and Ent schema boundaries so future agents can navigate high-risk areas without duplicating instructions. --- AGENTS.md | 87 ++++++++++++++++++++++++++++++++++++ backend/AGENTS.md | 63 ++++++++++++++++++++++++++ backend/ent/schema/AGENTS.md | 46 +++++++++++++++++++ backend/migrations/AGENTS.md | 45 +++++++++++++++++++ frontend/AGENTS.md | 64 ++++++++++++++++++++++++++ 5 files changed, 305 insertions(+) create mode 100644 AGENTS.md create mode 100644 backend/AGENTS.md create mode 100644 backend/ent/schema/AGENTS.md create mode 100644 backend/migrations/AGENTS.md create mode 100644 frontend/AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..fc6bcb1eea --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,87 @@ +# PROJECT KNOWLEDGE BASE + +**Generated:** 2026-03-29 20:34:51 CST +**Commit:** fdd8499f +**Branch:** opencode/curious-cactus + +## OVERVIEW +Sub2API is an AI API gateway platform: Go backend for routing, billing, auth, and persistence; Vue frontend for admin/user UI; Docker/systemd deploy assets for self-hosting. +Core stack: Go 1.26.1 + Gin + Ent + Wire + PostgreSQL/Redis, plus Vue 3 + Vite + Pinia + Vitest + TailwindCSS. + +## STRUCTURE +```text +curious-cactus/ +├── backend/ # Go runtime, persistence, generated Ent, SQL migrations +├── frontend/ # Vue app; build output embeds into backend/internal/web/dist +├── deploy/ # Docker/systemd install assets and config templates +├── .github/ # CI, security scan, release workflow +├── docs/ # Product/developer docs +└── tools/ # Repo utilities such as secret/audit helpers +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| Server bootstrap | `backend/cmd/server/main.go` | Setup mode, auto-setup, graceful shutdown | +| HTTP routing | `backend/internal/server/router.go` | Registers auth, user, admin, gateway routes | +| Business logic | `backend/internal/service/` | Covered by `backend/AGENTS.md` | +| Persistence | `backend/internal/repository/` | Ent + raw SQL + Redis caches | +| Schema edits | `backend/ent/schema/` | Covered by `backend/ent/schema/AGENTS.md` | +| Migration edits | `backend/migrations/` | Covered by `backend/migrations/AGENTS.md` | +| Frontend bootstrap | `frontend/src/main.ts` | Injected config before mount; router/i18n setup | +| Frontend routing | `frontend/src/router/index.ts` | Lazy routes, auth/admin/backend-mode guards | +| Admin API/UI | `frontend/src/api/admin/`, `frontend/src/views/admin/` | Covered by `frontend/AGENTS.md` | +| Deployment | `deploy/README.md`, `deploy/docker-compose.local.yml`, `deploy/install.sh` | Root file covers deploy-specific lookup | + +## CODE MAP +| Symbol | Type | Location | Role | +|--------|------|----------|------| +| `main` | function | `backend/cmd/server/main.go` | Entry point for setup mode and normal server mode | +| `runMainServer` | function | `backend/cmd/server/main.go` | Loads config, initializes app, starts server | +| `SetupRouter` | function | `backend/internal/server/router.go` | Applies middleware and mounts route groups | +| `ProviderSet` | variable | `backend/internal/service/wire.go` | Service-layer dependency graph root | +| `bootstrap` | function | `frontend/src/main.ts` | Frontend startup sequence | +| `router` | constant | `frontend/src/router/index.ts` | Route table + navigation guards + prefetch | + +## CONVENTIONS +- Use `pnpm`, not `npm`; CI installs frontend deps with `pnpm install --frozen-lockfile`. +- Frontend build output goes to `backend/internal/web/dist`; the backend can embed and serve it. +- Backend architecture is layered: `handler` and `service` must not import `repository` directly; lint enforces this. +- Ent output is generated; hand-written ORM work belongs in `backend/ent/schema/` and related mixins. +- SQL migrations auto-run on startup and are checksum-validated for immutability. +- Go version is pinned in CI and local tooling to `1.26.1`. + +## ANTI-PATTERNS (THIS PROJECT) +- Editing generated Ent files under `backend/ent/`. +- Modifying an already-applied migration instead of creating a new migration. +- Switching frontend package management to `npm` or changing `package.json` without updating `pnpm-lock.yaml`. +- Using API keys in query parameters; use the `Authorization` header. +- Relying on Sora-related features in production. + +## UNIQUE STYLES +- Frontend tests live in sibling `__tests__/` directories; backend tests are colocated as `*_test.go` with build tags such as `unit` and `integration`. +- Route metadata uses `titleKey`/`descriptionKey` for translated titles and page descriptions. +- Some frontend folders already carry rich README-style docs (`views/auth`, `router`, `stores`, `components/common`, `components/layout`); do not duplicate them blindly. +- Docker deployment favors `docker-compose.local.yml` because data stays in local directories and can be migrated by archiving the deploy folder. + +## COMMANDS +```bash +make build +make test + +cd backend && make generate +cd backend && make test-unit +cd backend && make test-integration + +cd frontend && pnpm install +cd frontend && pnpm run build +cd frontend && pnpm run lint:check +cd frontend && pnpm run typecheck +cd frontend && pnpm run test:run +``` + +## NOTES +- First-run setup can happen through the setup wizard or Docker auto-setup; do not assume a ready config exists. +- For self-hosted stability, keep `JWT_SECRET` and `TOTP_ENCRYPTION_KEY` fixed instead of letting them change every restart. +- When fronting Sub2API with Nginx for Codex CLI traffic, enable `underscores_in_headers on;`. +- Child instruction files exist at `backend/`, `backend/migrations/`, `backend/ent/schema/`, and `frontend/`; prefer the nearest one. diff --git a/backend/AGENTS.md b/backend/AGENTS.md new file mode 100644 index 0000000000..1adb8d910d --- /dev/null +++ b/backend/AGENTS.md @@ -0,0 +1,63 @@ +# BACKEND KNOWLEDGE BASE + +## OVERVIEW +`backend/` is the Go application: server bootstrap, config loading, DI, handlers, services, repositories, generated Ent ORM, and SQL migrations. +This is the authoritative layer for runtime rules, persistence architecture, and codegen boundaries. + +## STRUCTURE +```text +backend/ +├── cmd/server/ # Main binary, setup mode, Wire bootstrap +├── internal/ +│ ├── handler/ # HTTP handlers +│ ├── repository/ # Ent/raw SQL/Redis persistence +│ ├── service/ # Business logic, gateway, billing, ops +│ ├── server/ # Router and HTTP server wiring +│ ├── setup/ # Setup wizard and auto-setup +│ └── web/ # Embedded frontend serving +├── ent/ # Mostly generated code; handwritten work lives in schema/ +└── migrations/ # SQL migrations, checksum-protected +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| Bootstrap / flags | `cmd/server/main.go` | `--setup`, `--version`, auto-setup, shutdown | +| DI graph | `cmd/server/wire.go`, `internal/*/wire.go` | Wire provider sets | +| Routing / middleware | `internal/server/`, `internal/server/routes/`, `internal/server/middleware/` | Route mounting and auth middleware | +| Gateway logic | `internal/service/` | Multi-provider routing, billing, rate limiting | +| Persistence | `internal/repository/` | Ent client, Redis caches, raw SQL helpers | +| Config | `internal/config/config.go` | Large config surface; exact behavior lives here | +| Generated ORM | `ent/` | Do not edit generated output | +| Schema work | `ent/schema/` | See `ent/schema/AGENTS.md` | +| Migration work | `migrations/` | See `migrations/AGENTS.md` | + +## CONVENTIONS +- Go version is pinned to `1.26.1`; CI verifies it exactly. +- Keep layer boundaries intact: `handler` and `service` must not import `repository` directly. +- Ent is the ORM, Wire is the DI tool; schema/codegen changes are normal here. +- Frontend embedding is part of backend runtime: frontend build artifacts land in `internal/web/dist`. +- Test scopes use build tags such as `unit`, `integration`, and `e2e`. + +## ANTI-PATTERNS +- Editing generated Ent files under `ent/` instead of editing `ent/schema/`. +- Bypassing backend layering by importing persistence directly into `service` or `handler`. +- Changing Ent schema without regenerating code. +- Changing migration history in place. +- Treating setup/auto-setup as optional plumbing; startup behavior depends on it. + +## COMMANDS +```bash +cd backend && make build +cd backend && make generate +cd backend && make test +cd backend && make test-unit +cd backend && make test-integration +cd backend && go run ./cmd/server +``` + +## NOTES +- `internal/service/wire.go` is a high-signal navigation file even when you are not editing DI; it reveals the major backend subsystems. +- `internal/repository/migrations_runner.go` is the source of truth for how SQL files execute at runtime. +- Parent-level backend guidance should cover most subtrees; only migrations and handwritten Ent schema have separate child docs because their local failure modes are special. +- If a change touches auth, gateway routing, or admin behavior, expect to cross `handler`, `service`, and `repository` boundaries even if only one package is edited. diff --git a/backend/ent/schema/AGENTS.md b/backend/ent/schema/AGENTS.md new file mode 100644 index 0000000000..591662c548 --- /dev/null +++ b/backend/ent/schema/AGENTS.md @@ -0,0 +1,46 @@ +# ENT SCHEMA KNOWLEDGE BASE + +## OVERVIEW +`backend/ent/schema/` is the handwritten Ent enclave: entity definitions, mixins, edges, indexes, and annotations. +Edit schema here; generated files elsewhere under `backend/ent/` are outputs, not authoring surfaces. + +## STRUCTURE +```text +backend/ent/schema/ +├── *.go # Entity schemas +└── mixins/ + ├── soft_delete.go + └── time.go +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| Add/change entity fields | `*.go` in this directory | Entity-specific fields, edges, indexes, annotations | +| Shared timestamps | `mixins/time.go` | Common created/updated fields | +| Soft delete behavior | `mixins/soft_delete.go` | Custom interceptor/hook-based implementation | +| Code generation entry | `../generate.go` | `go:generate` feature list | +| Matching SQL migration | `../../migrations/` | Schema change should usually ship with migration | + +## CONVENTIONS +- Author schema changes here, not in generated Ent output. +- Reuse the local mixins where appropriate; this repo has a custom `SoftDeleteMixin` and a shared `TimeMixin`. +- Use annotations/indexes deliberately; table naming and SQL behavior are part of the handwritten schema contract. +- Treat schema edits and migration edits as one workflow, not separate chores. + +## ANTI-PATTERNS +- Editing `backend/ent/*.go` generated files instead of changing schema and regenerating. +- Introducing a schema change without the corresponding SQL migration when runtime data shape changes. +- Replacing the repo’s custom soft-delete pattern with Ent’s default soft-delete approach. +- Forgetting regeneration after schema edits. + +## COMMANDS +```bash +cd backend && go generate ./ent +cd backend && go generate ./cmd/server +``` + +## NOTES +- The parent `backend/` file owns the broad “generated Ent code is off-limits” rule; this child focuses on the handwritten authoring surface. +- `SoftDeleteMixin` is a repo-specific behavior boundary; read it before changing delete semantics. +- If a schema edit changes query semantics or constraints, check `internal/repository/` callers and add/update a migration. diff --git a/backend/migrations/AGENTS.md b/backend/migrations/AGENTS.md new file mode 100644 index 0000000000..30d01cacc6 --- /dev/null +++ b/backend/migrations/AGENTS.md @@ -0,0 +1,45 @@ +# MIGRATIONS KNOWLEDGE BASE + +## OVERVIEW +`backend/migrations/` contains forward-only SQL migrations executed by the backend’s custom runner. +This directory is high-risk because correctness depends on filename order, checksum immutability, and special handling for `_notx.sql` files. + +## STRUCTURE +```text +backend/migrations/ +├── NNN_description.sql # Transactional migrations +├── NNN_description_notx.sql # Non-transactional concurrent index migrations +└── README.md # Full migration workflow and rules +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| Migration rules | `README.md` | Naming, immutability, `_notx.sql`, troubleshooting | +| Runtime behavior | `../internal/repository/migrations_runner.go` | Checksums, advisory lock, execution mode | +| Applied migration state | `schema_migrations` table | Stores filename + checksum | + +## CONVENTIONS +- Name files as `NNN_description.sql` with zero-padded numeric prefixes. +- Keep migrations forward-only; if you need to revert behavior, add a new migration. +- `_notx.sql` is only for statements that must run outside a transaction, especially `CREATE/DROP INDEX CONCURRENTLY`. +- `_notx.sql` content must be idempotent: use `IF NOT EXISTS` / `IF EXISTS`. +- Files execute in lexicographic order, not by timestamp or folder. + +## ANTI-PATTERNS +- Editing a migration that may already have run in any environment. +- Renaming, deleting, or reordering existing migration files. +- Mixing regular DDL/DML or transaction control statements into `_notx.sql` files. +- Assuming goose-style Up/Down parsing exists; the runner executes the file content as-is. + +## COMMANDS +```bash +psql -d sub2api -c "SELECT * FROM schema_migrations ORDER BY applied_at DESC;" +git log --oneline -- backend/migrations/NNN_description.sql +``` + +## NOTES +- The application auto-runs migrations on startup; there is no separate migration binary here. +- Recovery from checksum mismatch is a Git/history problem first, not a SQL-edit-in-place problem. +- If a schema change starts in `backend/ent/schema/`, add the migration here in the same change set. +- Read `README.md` before touching `_notx.sql`; it contains repo-specific execution semantics. diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md new file mode 100644 index 0000000000..aee788848c --- /dev/null +++ b/frontend/AGENTS.md @@ -0,0 +1,64 @@ +# FRONTEND KNOWLEDGE BASE + +## OVERVIEW +`frontend/` is a Vue 3 application built with Vite, Pinia, Vitest, and TailwindCSS, then embedded into the Go backend. +This file owns frontend-wide rules: package management, bootstrap order, router conventions, API client shape, tests, and admin/user/auth UI patterns. + +## STRUCTURE +```text +frontend/ +├── package.json # pnpm scripts +├── vite.config.ts # Build, proxy, manual chunking, embed output path +├── vitest.config.ts # jsdom tests, coverage thresholds +└── src/ + ├── api/ # Axios client + API modules + ├── components/ # Shared UI by domain + ├── composables/ # Reusable view logic + ├── i18n/ # Translations and i18n bootstrapping + ├── router/ # Route table, guards, title handling + ├── stores/ # Pinia stores + ├── utils/ # Helpers + └── views/ # Auth, admin, user, setup pages +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| App bootstrap | `src/main.ts`, `src/App.vue` | Theme/init order, injected config, auth side effects | +| Routing / guards | `src/router/index.ts` | Lazy routes, auth/admin/backend-mode/simple-mode rules | +| API client | `src/api/client.ts`, `src/api/index.ts`, `src/api/admin/` | Interceptors, token refresh, admin API surface | +| Shared state | `src/stores/` | Auth, app UI, admin settings, subscriptions, onboarding | +| Shared UI | `src/components/` | Domain buckets such as `common`, `layout`, `account` | +| Reusable logic | `src/composables/` | Forms, OAuth, tables, navigation helpers | +| Auth flow docs | `src/views/auth/README.md` and companions | Existing local docs are strong; don’t duplicate them | + +## CONVENTIONS +- Use `pnpm`; CI expects `pnpm install --frozen-lockfile` and the lockfile to stay in sync. +- Build output goes to `../backend/internal/web/dist` because the backend embeds the frontend bundle. +- `src/main.ts` loads injected public settings before mount; respect that startup order when editing bootstrap code. +- Router entries are lazy-loaded and rely on metadata such as `requiresAuth`, `requiresAdmin`, `titleKey`, and `descriptionKey`. +- Tests are colocated in sibling `__tests__/` directories throughout `src/`. +- The admin API layer is centralized under `src/api/admin/index.ts`; prefer extending that pattern instead of ad hoc fetch code. + +## ANTI-PATTERNS +- Switching package management to `npm` or changing deps without updating `pnpm-lock.yaml`. +- Bypassing the shared API client/interceptors for normal application requests. +- Breaking the injected-config-before-mount flow in `src/main.ts`. +- Duplicating route-title logic in components instead of using router metadata and title helpers. +- Creating subtree docs that restate frontend-wide rules already covered here or in existing README files. + +## COMMANDS +```bash +cd frontend && pnpm install +cd frontend && pnpm run dev +cd frontend && pnpm run build +cd frontend && pnpm run lint:check +cd frontend && pnpm run typecheck +cd frontend && pnpm run test:run +cd frontend && pnpm run test:coverage +``` + +## NOTES +- Existing local docs are already strong in `src/router/`, `src/stores/`, `src/components/common/`, `src/components/layout/`, and `src/views/auth/`; use them instead of copying them into new AGENTS files. +- Keep admin and admin/ops work under this parent unless truly local rules emerge; current evidence shows shared router/store/API conventions matter more than directory size. +- `views/admin/ops/` is deep, but its rules still depend on shared frontend patterns such as admin routing, centralized admin APIs, and store-driven UI state. From 56777e71911db03363ba72044cb56244cfb4d744 Mon Sep 17 00:00:00 2001 From: YanzheL Date: Sun, 29 Mar 2026 21:18:40 +0800 Subject: [PATCH 2/2] docs: refine AGENTS hierarchy for backend and deploy workflows --- AGENTS.md | 12 ++++++---- backend/AGENTS.md | 20 ++++++++++++---- deploy/AGENTS.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 deploy/AGENTS.md diff --git a/AGENTS.md b/AGENTS.md index fc6bcb1eea..d47386c046 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,8 @@ # PROJECT KNOWLEDGE BASE -**Generated:** 2026-03-29 20:34:51 CST -**Commit:** fdd8499f -**Branch:** opencode/curious-cactus +**Generated:** 2026-03-29 21:13:36 CST +**Commit:** 941a44da +**Branch:** feat/agents-md ## OVERVIEW Sub2API is an AI API gateway platform: Go backend for routing, billing, auth, and persistence; Vue frontend for admin/user UI; Docker/systemd deploy assets for self-hosting. @@ -31,7 +31,9 @@ curious-cactus/ | Frontend bootstrap | `frontend/src/main.ts` | Injected config before mount; router/i18n setup | | Frontend routing | `frontend/src/router/index.ts` | Lazy routes, auth/admin/backend-mode guards | | Admin API/UI | `frontend/src/api/admin/`, `frontend/src/views/admin/` | Covered by `frontend/AGENTS.md` | -| Deployment | `deploy/README.md`, `deploy/docker-compose.local.yml`, `deploy/install.sh` | Root file covers deploy-specific lookup | +| Deployment / self-hosting | `deploy/` | See `deploy/AGENTS.md` for compose variants, install scripts, and socket/path gotchas | +| Repo tooling | `tools/` | Small helper scripts such as audit/exception checks | +| Product/API docs | `docs/` | Start here for integration-facing docs before editing code | ## CODE MAP | Symbol | Type | Location | Role | @@ -84,4 +86,4 @@ cd frontend && pnpm run test:run - First-run setup can happen through the setup wizard or Docker auto-setup; do not assume a ready config exists. - For self-hosted stability, keep `JWT_SECRET` and `TOTP_ENCRYPTION_KEY` fixed instead of letting them change every restart. - When fronting Sub2API with Nginx for Codex CLI traffic, enable `underscores_in_headers on;`. -- Child instruction files exist at `backend/`, `backend/migrations/`, `backend/ent/schema/`, and `frontend/`; prefer the nearest one. +- Child instruction files exist at `backend/`, `backend/migrations/`, `backend/ent/schema/`, `frontend/`, and `deploy/`; prefer the nearest one. diff --git a/backend/AGENTS.md b/backend/AGENTS.md index 1adb8d910d..678771ca4a 100644 --- a/backend/AGENTS.md +++ b/backend/AGENTS.md @@ -1,19 +1,28 @@ # BACKEND KNOWLEDGE BASE ## OVERVIEW -`backend/` is the Go application: server bootstrap, config loading, DI, handlers, services, repositories, generated Ent ORM, and SQL migrations. +`backend/` is the Go application: server bootstrap, config loading, DI, handlers, services, repositories, shared protocol/client helpers, generated Ent ORM, and SQL migrations. This is the authoritative layer for runtime rules, persistence architecture, and codegen boundaries. ## STRUCTURE ```text backend/ +├── cmd/jwtgen/ # JWT secret helper binary ├── cmd/server/ # Main binary, setup mode, Wire bootstrap ├── internal/ +│ ├── config/ # Config loading and validation +│ ├── domain/ # Shared domain constants and models │ ├── handler/ # HTTP handlers +│ ├── integration/ # End-to-end backend test flows +│ ├── middleware/ # Shared middleware such as rate limiting +│ ├── model/ # Shared model structs +│ ├── pkg/ # Shared protocol/client/helper packages │ ├── repository/ # Ent/raw SQL/Redis persistence -│ ├── service/ # Business logic, gateway, billing, ops +│ ├── service/ # Account, auth, gateway, billing, ops, subscriptions │ ├── server/ # Router and HTTP server wiring │ ├── setup/ # Setup wizard and auto-setup +│ ├── testutil/ # Backend test fixtures and helpers +│ ├── util/ # Focused utility packages │ └── web/ # Embedded frontend serving ├── ent/ # Mostly generated code; handwritten work lives in schema/ └── migrations/ # SQL migrations, checksum-protected @@ -24,10 +33,12 @@ backend/ |------|----------|-------| | Bootstrap / flags | `cmd/server/main.go` | `--setup`, `--version`, auto-setup, shutdown | | DI graph | `cmd/server/wire.go`, `internal/*/wire.go` | Wire provider sets | -| Routing / middleware | `internal/server/`, `internal/server/routes/`, `internal/server/middleware/` | Route mounting and auth middleware | -| Gateway logic | `internal/service/` | Multi-provider routing, billing, rate limiting | +| Routing / middleware | `internal/server/`, `internal/server/routes/`, `internal/middleware/` | Router setup, route registration, shared middleware | +| Service layer | `internal/service/` | Flat package spanning auth, account, admin, gateway, billing, ops, subscriptions, Sora | | Persistence | `internal/repository/` | Ent client, Redis caches, raw SQL helpers | | Config | `internal/config/config.go` | Large config surface; exact behavior lives here | +| Shared helpers / clients | `internal/pkg/`, `internal/util/`, `internal/domain/` | Protocol adapters, logging, validation, shared constants | +| Backend e2e tests | `internal/integration/`, `internal/testutil/` | Integration harnesses, fixtures, HTTP helpers | | Generated ORM | `ent/` | Do not edit generated output | | Schema work | `ent/schema/` | See `ent/schema/AGENTS.md` | | Migration work | `migrations/` | See `migrations/AGENTS.md` | @@ -58,6 +69,7 @@ cd backend && go run ./cmd/server ## NOTES - `internal/service/wire.go` is a high-signal navigation file even when you are not editing DI; it reveals the major backend subsystems. +- `internal/service/` is intentionally broad and flat; use filename prefixes plus `wire.go` to navigate instead of expecting child docs under that subtree. - `internal/repository/migrations_runner.go` is the source of truth for how SQL files execute at runtime. - Parent-level backend guidance should cover most subtrees; only migrations and handwritten Ent schema have separate child docs because their local failure modes are special. - If a change touches auth, gateway routing, or admin behavior, expect to cross `handler`, `service`, and `repository` boundaries even if only one package is edited. diff --git a/deploy/AGENTS.md b/deploy/AGENTS.md new file mode 100644 index 0000000000..d4122b8ac4 --- /dev/null +++ b/deploy/AGENTS.md @@ -0,0 +1,59 @@ +# DEPLOYMENT KNOWLEDGE BASE + +## OVERVIEW +`deploy/` is the operator-facing subtree for Docker Compose, systemd installs, env templates, and deployment scripts. + +## STRUCTURE +```text +deploy/ +├── docker-compose.local.yml # Preferred local-directory deployment +├── docker-compose.yml # Named-volume deployment +├── docker-compose.dev.yml # Build-from-source local development +├── docker-compose.standalone.yml # App-only deployment with external Postgres/Redis +├── docker-deploy.sh # One-click Docker preparation +├── install.sh # Binary install / upgrade / uninstall +├── docker-entrypoint.sh # Container permission fix + exec wrapper +├── .env.example # Docker env template +├── config.example.yaml # Binary/systemd config template +└── sub2api.service # Systemd unit +``` + +## WHERE TO LOOK +| Task | Location | Notes | +|------|----------|-------| +| Choose Docker variant | `docker-compose.local.yml`, `docker-compose.yml`, `docker-compose.standalone.yml` | Local directories are preferred; standalone expects external services | +| One-click Docker setup | `docker-deploy.sh` | Downloads local compose/env templates and generates secrets | +| Binary install / upgrade | `install.sh`, `sub2api.service` | Systemd path is `/opt/sub2api`; setup wizard remains relevant here | +| Container startup behavior | `docker-entrypoint.sh` | Fixes `/app/data` ownership, then re-execs as `sub2api` | +| Environment variables | `.env.example`, `config.example.yaml` | Docker favors env vars; binary install can use config YAML | +| Data management daemon | `DATAMANAGEMENTD_CN.md`, `install-datamanagementd.sh` | Socket path is fixed at `/tmp/sub2api-datamanagement.sock` | + +## CONVENTIONS +- Prefer `docker-compose.local.yml` for self-hosted deployments because data lives in local directories and migrates cleanly by archiving the deploy folder. +- Docker deployments rely on `AUTO_SETUP=true`; binary/systemd deployments still expect the normal setup wizard flow. +- Keep `JWT_SECRET` and `TOTP_ENCRYPTION_KEY` fixed across restarts; empty values trigger random regeneration and break sessions or 2FA. +- `docker-compose.standalone.yml` is only for environments with externally managed PostgreSQL and Redis. +- Container and service units run as `sub2api`; permission fixes happen in entrypoint/service setup, not in app code. + +## ANTI-PATTERNS +- Using named-volume compose when you actually need easy backup/migration behavior. +- Removing or changing `PGDATA=/var/lib/postgresql/data` in `docker-compose.yml`; Postgres 18 otherwise falls back to the image default path and can appear to lose data after recreate. +- Assuming PostgreSQL or Redis are exposed on the host by default; the compose files keep them on the internal network unless you add debug ports yourself. +- Treating `JWT_SECRET` or `TOTP_ENCRYPTION_KEY` as optional in long-lived deployments. +- Moving the datamanagementd socket to a different path without updating the host/container mount strategy. + +## COMMANDS +```bash +cd deploy && cp .env.example .env +cd deploy && docker compose -f docker-compose.local.yml up -d +cd deploy && docker compose -f docker-compose.local.yml logs -f sub2api +cd deploy && docker compose -f docker-compose.local.yml down +cd deploy && sudo ./install.sh +cd deploy && sudo ./install.sh upgrade +``` + +## NOTES +- `docker-deploy.sh` downloads `docker-compose.local.yml` but saves it as `docker-compose.yml`; read the script before assuming the filename tells you which variant is in use. +- `install.sh` is bilingual and defaults to Chinese in non-interactive `curl | bash` flows. +- `sub2api.service` uses hardening flags such as `NoNewPrivileges=true` and `ProtectSystem=strict`; preserve those unless deployment requirements truly change. +- Keep root deployment guidance pointer-oriented; deploy-specific gotchas should live here.