Skip to content

Architecture Decision Records (ADRs)

ADRs (Architecture Decision Records) document important technical decisions: what was decided, why, and which alternatives were discarded.

The full files are in docs/es/adr/.

Index

ADR Title Status
ADR-001 Microservices architecture with FastAPI Accepted
ADR-002 Multi-tenancy with schema isolation in PostgreSQL Accepted
ADR-003 Direct asyncpg instead of SQLAlchemy ORM Accepted
ADR-005 Batch operations API Accepted
ADR-006 Configurable AI provider (multi-provider, global) for the knowledge layer Proposed
ADR-007 Document metadata with template-validated JSONB Proposed
ADR-008 Immutable audit with hash-chained audit_log Proposed
ADR-009 Flow history as append-only events + projection Proposed
ADR-010 Shared library orpycamcp_common (audit and events) Accepted
ADR-011 SvelteKit frontend (SSR) as the presentation app in the monorepo Proposed
ADR-012 Per-tenant migrations (runner global/ + tenant/) Accepted
ADR-013 Authorization resolved in the DB per request (Keycloak authenticates, the DB authorizes) Accepted
ADR-014 Search with PostgreSQL FTS (tsvector + pg_trgm + JSONB), not Elasticsearch Accepted
ADR-015 TRD/CCD model: series↔subseries hierarchy, two-phase retention, AGN disposition (CT/E/S/M) Accepted
ADR-016 Native electronic signature (SHA-256 hash + identity + timestamp), PKI/PDF deferred Accepted
ADR-017 Physical archive: location (recursive address) ≠ conservation unit (mobile container), ArchivesSpace pattern Accepted
ADR-018 Outgoing interoperability via signed HTTP webhooks (HMAC-SHA256) over the event bus, subscribed per tenant Accepted
ADR-019 MCP layer as a thin gateway-client facade (declarative tool catalog, no logic or DB) Accepted
ADR-020 Orpyca design system (Sass tokens + custom properties, per-tenant branding) and conversational assistant (text/voice) as a translator to MCP tools with local opt-in AI Proposed
ADR-021 PEL reclamation and per-consumer-group dead-letter in Redis Streams (signature/workflow/notification-service) Accepted
ADR-022 Electronic index v2 profile — RT-15 metadata per document (format, size, foliation) Accepted
ADR-023 WORM / Object-Lock for preservation (MinIO) and the AIP/PREMIS roadmap Accepted (Increment A)
ADR-024 USUA_PERM_ROOT is never granted through the API — an entity administrator is not the ceiling of their own entity; ROOT is provisioned out of band only Accepted
ADR-025 The TRD is a convalidated instrument, not a configuration table: append-only versioning and pinning of the version that governs each expediente Implemented (Increments 1+2)
ADR-026 The TVD is the same instrument with different content: a tipo_instrumento discriminator on trd_series, not its own table (registration and convalidation circuit for an accumulated fonds) Implemented (Increment 1)
ADR-027 MinIO archived its open-source project and pulled its images: the object store moves to RustFS, and the engine is chosen by a WORM conformance battery against a real S3 (RustFS 7/7, MinIO 7/7, Garage 0/7), not by a datasheet Implemented
ADR-028 The workflow moves the radicado's status: one pure function written in the same transaction as the step, closing only via an explicit "Finish processing", closed/anulado terminal (409) and holder-only marcar_leido; audit remediation: clearance and holder gates on assign/transfer, annulment cancels the step, immutable backfill evidence Implemented
ADR-029 Current location of the radicado: three flujo_* columns written by workflow-service in the same UPDATE as the status, two generated ubicacion_* columns (computed as pairs), one pure derivar_ubicacion function (last step by when it closed, not by its number), code only when the name is unique, backfill with insert-only evidence, and kept out of everything public Implemented
ADR-031 Authorization record: gateway-signed IP on public routes, per-entity data-processing policy served and re-read by the server, and a delivery receipt with author and no reuse Accepted
ADR-032 The dependencia is correlated by code, not by name: immutable codigo (trigger + 422), a single resolver_codigo_dependencia function with name history, code-canonical contract with the name as deprecated alias, fail-closed backfill on ambiguity, deactivate/delete by code Accepted
ADR-033 Production entry: containerised nginx (edge) as the only service with ports, TRUSTED_PROXIES without the network's gateway so the sealed IP cannot be forged, Keycloak published only on /realms/ and /resources/, and third-party images pinned by tag and digest Accepted
ADR-034 The XAdES signature is declared as it is applied: explicit Transforms on the references signxml leaves without them, SignedInfo signed after the patch (seal and personal signature), fail-closed self-verification with a default XAdESVerifier(), no canonicalisation shortcut when verifying, and ArchiveTimeStamp input per EN 319 132-1 §5.5.2; validated against EU DSS Accepted
ADR-035 Entity state is enforced at the edge: /auth/validate reports tenant_estado, the api-gateway vetoes (403 tenant_inactivo, 503 tenant_no_provisionado/tenant_estado_no_disponible, fail-closed) within its 15 s cache TTL, every get_tenant_conn re-checks it before the search_path, a suspended entity keeps its public reads (verification, OAI, CMIS, disposal publicity) and closes its writes with 503 canal_no_disponible, while non-existent, deactivated and unprovisioned entities answer an identical 404; login issues no token to a non-operational entity and the signed identity expires after 120 s; event consumers and background tasks are deliberately excluded Accepted
ADR-036 The signed identity is bound to the request method and path: both enter the HMAC base (v2) without travelling as headers, ruta_canonica (no query, decoded to a fixed point) is identical on signer and verifier, the API has no defaults and an AST guardian requires the signed path to be the called one; an identity replayed on another operation gets 401 identidad_no_autentica and deployment is an atomic cut-over Accepted

How to propose a new ADR

  1. Create the file docs/es/adr/ADR-{NNN}-{slug}.md
  2. Use the standard format: Context, Decision, Consequences, Alternatives
  3. Update this page with the new ADR
  4. Open an MR for discussion before marking it as "Accepted"