Project catalogue records, search, facets and project document metadata/chunks are public. Only publish material appropriate for an open archive. This API is not a confidential project-document repository. Project document routes verify that the requested document belongs to the named project; an RFP brief cannot be read through a project route.
RFP routes require a valid JWT and check ownership against PostgreSQL. Creating/editing briefs, uploading documents and running matches require EDITOR or ADMIN. Account provisioning is an operator responsibility; there is no public registration endpoint. Operational index/reconciliation APIs and detailed actuator metrics require ADMIN. The performance corpus controller additionally uses @Profile("!prod") and must remain non-production.
The browser exposes reading, search and owned RFP matching. It has no ingestion, index administration, maintenance, performance-fixture or failure-simulation controls.
Passwords use BCrypt. Login returns a short-lived HS256 access token and identity; failure responses do not distinguish an unknown user from an incorrect password. Token validation verifies its signature and expiry. Roles authorize operations; RFP ownership comes from the database, not a browser claim.
Frontend tokens exist only in module memory. They are not stored in cookies, browser storage, URLs or static configuration. Reload, sign-out and expiry end the frontend session. Use HTTPS and the intended trusted API origin in deployment. Stateless bearer authentication permits CSRF protection to remain disabled because authentication is not cookie-borne; introducing cookies would require revisiting this assumption.
CORS permits explicit origins, methods and headers, exposes X-Request-Id, and does not enable credentialed cookies. Local defaults are http://127.0.0.1:5179 and http://localhost:5179. Production requires DESIGN5_ALLOWED_ORIGINS. Never replace this with an unrestricted production wildcard.
The frontend API layer allowlists DTO fields and normalizes errors. Raw database, storage, queue and Java diagnostics are not customer-facing copy. The loopback development server serves an explicit asset allowlist and refuses repository files, environment files and runtime directories. A deployed server must preserve an equivalent public-file boundary.
Supply database, JWT, embedding and infrastructure credentials through environment variables or a secret manager. No fixed development password is distributed. Local demo account creation is opt-in, requires a supplied password, and the loader is excluded under prod. Isolated tests use clearly synthetic fixtures and a disposable database; they do not provision production users.
The production profile requires database credentials, allowed origins, AWS/storage/search settings and a real embedding provider. It cannot silently fall back to the deterministic provider. A deployment must activate prod; local profiles intentionally support local-only services without production transport controls. Docker's runtime default is prod,api.
Never commit .env, private .tfvars, backend credentials, Terraform state, logs, dumps or document storage. Environment variables are not a substitute for host/process access controls. Do not print them in diagnostics or pass credentials in command-line arguments.
The backend validates supported media kinds and size bounds, uses internal storage keys and bounds text extraction/chunk sizes. Original filenames are metadata, not filesystem paths. Filesystem/S3 implementations keep storage details out of public DTOs. Failed requests use structured error codes and a correlation ID; operational diagnostics remain in restricted logs. Treat user-supplied document text as untrusted content; the frontend renders text with safe DOM APIs.
Flyway owns the schema, validates checksums and disables cleaning. Integration tests guard the exact disposable database name and clear only test data. Existing application databases require read-only inspection and an owner-approved backup/reconciliation plan before schema work. No automatic baseline, repair or reset is part of startup.
Terraform defines private application/data networking, security-group-scoped access, encrypted data services, private S3 and task roles. Worker HTTP endpoints are not protected merely by selecting the worker profile: keep workers off public load balancers and restrict their network access. The local OpenSearch and ElasticMQ configurations disable production-grade authentication and bind through loopback; they are local development services only.
Secrets Manager injects task credentials. Terraform-created secret values are present in Terraform state, even when outputs are marked sensitive. Protect remote state with encryption, access control, locking and restricted backups. Do not publish state or plan files. ARN-only outputs do not make the underlying state non-sensitive.
The repository has no deployment workflow and no automatic provisioning trigger. Infrastructure definitions require an explicit operator plan, review and deployment procedure. Alert subscriptions, public DNS/certificates, API routing and operational access are deployment responsibilities.
Maven verification runs Spotless, unit/integration tests, packaging and SpotBugs. The optional sbom profile emits a dependency inventory. Frontend boundary and browser checks cover sanitized errors, memory-only sessions, CORS, unauthorized API access and the static file allowlist. These checks do not replace a deployment security review or a vulnerability assessment of the chosen production environment.
Dependency notices are recorded in dependencies.md. Do not publish a credential or private document in an issue. If a credential is exposed, revoke or rotate it at its provider; deleting a file or rewriting Git history does not revoke access.