- Documentation maintainer: Enzo Ribas (@oEnzoRibas).
| Variable | Default / requirement | Purpose |
|---|---|---|
| DB_HOST / DB_PORT | localhost / 5435 outside Compose; database / 5432 inside | PostgreSQL endpoint |
| DB_NAME / DB_USER | irr / irr_app | Development database identity |
| DB_PASSWORD | Required; local .env for Compose | Database credential |
| SERVER_PORT | 9191 | Application listener; Compose expects this container port |
| API_PORT | 9191 in Compose | Loopback host binding |
| RSA_PUBLIC_KEY / RSA_PRIVATE_KEY | file:./.local/keys/*.pem; overridden by Compose | External key locations |
| DEV_ADMIN_EMAIL / DEV_ADMIN_PASSWORD | Required when bootstrap enabled | Local administrator login; password hashed before persistence |
| DEV_ADMIN_NAME / DEV_BOOTSTRAP_ENABLED | Development Administrator / true in Compose | Explicit development-only provisioning |
| COMPOSE_PROJECT_NAME | irr-development | Fresh baseline isolation from old volumes |
| API_DOCS_ENABLED | true in development | Enables Swagger UI and OpenAPI; false disables anonymous documentation access |
| STORAGE_DIRECTORY | ./.local/uploads; /data/uploads in Compose | Persistent upload directory |
Spring Boot does not automatically load .env for a host JVM. Export variables before mvnw spring-boot:run. The default Compose database is not published; use Compose for the whole stack or explicitly configure a separate host-development database. Never point integration tests at that database. Tests derive credentials exclusively from their disposable container.
Use the root README sequence. Generate keys using Java 21 once; the script refuses existing files. On Unix, restrict the local key directory to the development account; ensure the container's UID can read the mounted files. Local bind mounts do not provide a production secret manager. Database password changes in .env do not rotate a role password in an already initialized PostgreSQL volume.
Compose starts PostgreSQL and authenticated Redis, waits for both health checks, then boots the API. Flyway applies SQL, Hibernate validates mappings, and readiness reports UP only after application/DB health succeeds. Check docker compose logs backend when health does not pass. A missing key file, invalid migration or wrong password is an error to fix, not a reason to disable validation.
ADR-0014 uses new database_final_v1 and attachment_final_v1 logical volumes, prefixed by the Compose project. Earlier database_data and attachment_data volumes remain intact. Redis retains its existing independent volume. Do not reconnect the final V1 image to an earlier migration history. Restore the matching previous application/database snapshot for rollback, or prepare a deliberate data import into the new baseline.
ADR-0014 established V1__initial_schema.sql as the fresh baseline. The active Flyway path now contains V1 plus additive V2 credential lifecycle, V3 password recovery and V4 Routes. Fresh databases apply all four; existing databases retain their checksums and apply only missing versions. Never run Flyway repair or baseline-on-migrate to conceal a mismatch with the unreleased predecessor.
Earlier SQL is recoverable from Git history at commit 3ca0cab. Duplicate SQL archives were removed from the maintained tree. The private pre-consolidation backup and old volumes preserve actual local data. Existing creator identities are insufficient evidence for organization mapping.
Future shared changes use versions after the highest applied version (currently V5+). Add new DDL, test a populated-baseline upgrade, verify failures roll back, and document any necessary preflight/backfill. Unique/nonnegative inventory constraints are already part of the baseline.
For valuable development data, stop writes and export PostgreSQL with pg_dump together with a consistent attachment archive and metadata manifest. Keep RSA keys outside the repository and outside published reports. Restore into a separate named project/database, validate Flyway history and attachment references, then run health and representative reads. Do not claim recoverability without a restore exercise. Docker volumes are persistence, not backups.
After a failed migration, inspect logs and transaction outcome before restarting. Transactional PostgreSQL migrations must leave the schema unchanged on failure, as checked by the integration fixture. Reconcile data in a reviewed follow-up; rerun migration on the isolated copy first. Once new application writes rely on new constraints/schema, rollback needs an explicitly tested prior application/schema pair; deleting an applied migration from source does not undo it.
Use Java 21 and ./mvnw clean verify (Windows: .\mvnw.cmd clean verify). Docker must be running. Testcontainers creates its own random-port PostgreSQL instance and removes test containers after the JVM exits. A missing runtime fails tests. Integration classes end with IT; unit tests run in Surefire, integrations in Failsafe. Never use skipTests as release evidence; the Docker build skips test execution because CI performs verification separately.
For a container smoke test, create a unique Compose project name and an unused API_PORT so existing environments are untouched. Validate configuration with docker compose config --quiet, build, start with --wait, check /actuator/health/readiness, then stop that named project. Preserve volumes unless they were created solely as disposable test fixtures. Keep passwords out of command output and image layers.
This is a local single-host topology. Public TLS, backup scheduling, resource sizing, release image digests, least-privilege runtime/migration database roles and external secret management are later release work. No Kubernetes cluster is required by current evidence. The local authorization/domain workflow is verified; public deployment and frontend release pairing remain separate gates.
The final V1 includes the durable deletion queue. Future changes use additive V2+ migrations. Rebuild with docker compose up --build -d --wait. The cleanup scheduler runs every 60 seconds; irr.attachments.cleanup-enabled=false is reserved for deterministic tests or deliberate maintenance. A successful API delete returns 202 after committing metadata removal and the queue job, not after physical deletion.
Inspect retry backlog from a database session with:
SELECT id, created_at, attempts, next_attempt_at, last_error
FROM attachment_file_deletion
ORDER BY created_at;Repeated failures require checking the attachment volume mount, storage availability and UID 10001 permissions. The worker retries idempotently; do not manually delete queue rows to conceal a storage error. A crash during upload can leave unreferenced bytes. The hourly orphan reconciler uses a 24-hour grace period and an exclusive advisory lock against upload transactions; inspect metadata and backups before any manual cleanup. Backups must include both committed metadata and attachment content.
The final V1 creates 29 application tables. Organization membership and access audit are part of that baseline, and no ownership is inferred from the creator. Administrative effects and audit records commit together. ADR-0016 adds the runtime V2 credential fields; V3 adds runtime password recovery authorization. Test-only incremental V5 examples remain outside the runtime image.
Compose now starts PostgreSQL, authenticated Redis and the API. Redis uses the internal network, a separate persistent volume and no host port. Both data services must pass health checks before API startup; readiness includes both. Redis credentials are required in the ignored .env and should be rotated together on Redis/backend recreation. The README Redis workflow provides commands. Redis AOF is neither a PostgreSQL backup nor a stock/authorization authority.
Use Node.js 22.6+ and select the actual stack explicitly. The current worktree command is node scripts/backup-development.mjs --compose-file .local/identity/compose.json --project irr-identity-verification. For the standard root Compose stack, omit arguments; optional --env-file selects its interpolation environment. The script validates running service/configuration identity, stops the selected API, archives PostgreSQL, attachments, resolved private configuration and actual RSA keys, then restarts and waits for health. Format 2 records image IDs, table counts and individual attachment hashes. See the current recovery runbook and evidence. Keep the directory private; Windows account ACLs remain the operator's responsibility. A partial snapshot without a valid complete manifest is not accepted.
Run node scripts/verify-recovery.mjs followed by the printed backup directory. The tool checks required hashes, creates a labeled PostgreSQL container from the archived local image with no network or host ports, restores SQL with exit-on-error, compares migration checksums and table counts, validates archive paths and file bytes, resolves attachment references and checks stock against ledger and lots. It removes only its labeled disposable container and anonymous volume. The 2026-10-10 V1-V4 rehearsal restored 39 tables, 20 attachment files/references and zero stock differences. This proves local recovery consistency; it does not automatically roll back the live application.
Historical ADR-0013 verification on 2026-09-27: the pre-upgrade V1–V3 snapshot restored; the post-upgrade V1–V6 snapshot restored with 30 public tables (including Flyway history), two attachment fixture files and zero stock differences. Checksums are recorded in local manifests. Backup retention and off-machine encrypted storage remain the operator responsibility before any valuable deployment.
DEV_ORGANIZATION_ID and DEV_ORGANIZATION_NAME identify one development organization. Bootstrap creates its explicit administrator MANAGER association only on first creation. It does not restore revoked access or inactive organizations. Keep the UUID stable across restarts. Production has no development bootstrap.
The preserved predecessor database may contain old business rows with null organization_id. They are deliberately invisible through scoped APIs; creator_id is not a valid organization mapping. A legacy import requires reviewed ownership, reference closure and opening-stock provenance. Do not guess ownership, alter Flyway checksums or expose null-scoped data.
Check readiness for PostgreSQL and Redis, liveness for the process, and Docker health. A healthy process does not prove inventory consistency: use the authenticated organization reconciliation endpoint. Investigate any nonzero difference before further operational writes; never overwrite immutable movements to make a report match.
Attachment deletion queues persist in PostgreSQL. The existing worker retries failed physical deletion. The hourly orphan reconciler scans at most 500 eligible candidates per invocation after a 24-hour grace period, with a cursor and an exclusive database advisory lock that excludes upload transactions. Local directory sorting still traverses the directory; monitor volume growth and move to paged storage reconciliation if scale requires it. Do not manually delete referenced bytes.
Legacy operational summaries retain their UTC semantics. Native operations-1 and analytics-1 use explicitly documented America/Sao_Paulo periods and independent fact cohorts; see reporting and Analytics. Reports remain uncached; reversals recalculate applicable historical contributions. Redis holds no recoverable business truth today. Readiness depends on Redis by ADR-0010 policy; stop/start Redis only during a controlled local resilience test.
ADR-0014 supersedes the active V1–V6 chain and compatibility API. All application requests now use /api/v1, including session authentication, account administration and organizations. Documentation and actuator infrastructure retain their framework URLs. The ADR-0014 restoration below verified the one-version predecessor baseline. Current restore evidence must include successful V1/V2/V3/V4 after Identity and Routes upgrades, not the historical six-row sequence.
The independent schema fixture records 560 column/default/nullability, constraint, index, trigger and domain-function definitions from the verified predecessor. FinalBaselineSchemaIT compares the fresh schema exactly after removing schema qualification and whitespace. Test-only V5 examples prove future upgrades and transactional failure rollback. Production migration discipline begins with this final shared baseline.
Final ADR-0014 rehearsal on 2026-09-27 restored V1 checksum 583196656, 30 public tables including Flyway history, one uploaded evidence file and zero stock differences. The script also verifies that every restored attachment metadata reference resolves to a canonical file in the archive. Earlier six-migration results above are historical only.
OPTION A — INCREMENTAL: preserve V1 and apply V2__account_credential_lifecycle.sql automatically. V2 adds credential_version and must_change_password for token revocation and restricted temporary credentials. A fresh database runs V1/V2, V3 recovery and V4 Routes migrations. After operational data must be retained, never rewrite applied migrations, erase history, use clean or reset PostgreSQL as normal maintenance. Future changes use new versions.
Development bootstrap no longer resets existing credentials or profiles. Use authenticated password change; editing a local .env is not a password reset mechanism. Optional BOOTSTRAP_ADMIN_* provisioning is separate and disabled by default. See Railway deployment for the first-account process and security-aware rollback. No remote database recreation is part of this delivery.
ADR-0017 supersedes earlier no-bypass administrator rules. Global administrators access any active organization through an explicit organization header; local accounts require current memberships. Actual membership discovery never fabricates a global association. Preserve the last active global administrator.
ADR-0018 adds V3__password_recovery.sql without resetting V1/V2 or existing accounts. The Identity delivery baseline was V1 + V2 + V3; the current Routes baseline also includes V4; earlier one-version restoration counts above are dated predecessor evidence. Recovery is enabled explicitly, throttled through Redis and atomically consumed in PostgreSQL. Follow email recovery operations and the Railway mail checklist. Backend readiness does not test sender verification or inbox arrival. Test-only V5 examples demonstrate future upgrades; they are not runtime migrations.
Identity is IMPLEMENTED / READY FOR HOMOLOGATION. Email provider deployment is OPERATIONAL CONFIGURATION PENDING / EXTERNAL CONFIGURATION REQUIRED: approved Brevo account, sender/domain DNS verification, backend-only API key and public reset URL. Follow the implemented email runbook for exact variables, local no-internet tests, real-inbox smoke and troubleshooting. This operational configuration does not block owner-authorized Routes development. No external credentials or Railway changes were performed locally.
Current runtime is V1 + V2 + V3 + V4. V4 adds normalized territory/planning/execution history and optional collection linkage; no reset is required. Earlier V3 verification counts above are dated Identity evidence. Test-only future migration examples are now V5, outside the runtime image. Routes operations describes deployment order, preserved storage, version conflicts, history and rollback constraints. No new service or Railway variable is required. External email configuration remains a parallel operational dependency, not a Routes development gate.