1- # FR5e — Database-source loader errors (sketch, future)
1+ # FR5e — Database-source loader errors
22
3- ** Status:** Forward-looking — gated on FR-003 (OMDB persistence engine)
4- ** Date:** 2026-05-25
5- ** Scope:** Java first (FR-003 is the Java OMDB persistence engine), then any port that
6- gains database-sourced metadata loading.
7- ** Depends on:** [ ADR-0009] ( ../../../spec/decisions/ADR-0009-loader-error-envelope-and-source-on-node.md ) (the ` format: "database" ` slot is already reserved), FR-003 (database-loader implementation).
3+ ** Status:** Schema reserved + cross-port envelope shape locked (2026-05-27). Awaiting a real database-source loader.
4+ ** Date:** 2026-05-25 (sketched), 2026-05-27 (design questions resolved + per-port shape tests added)
5+ ** Scope:** Java first (FR-003 ships the OMDB persistence engine), then any port that gains database-sourced metadata loading.
6+ ** Depends on:** [ ADR-0009] ( ../../../spec/decisions/ADR-0009-loader-error-envelope-and-source-on-node.md ) (the ` format: "database" ` slot was always reserved).
7+
8+ ## What's shipped
9+
10+ The envelope schema is fully locked across all four ports:
11+
12+ | Port | Source type | Location |
13+ | ---------| ----------------------------| ----------|
14+ | TS | ` format: "database"; dbLocation: { table, id }; jsonPath? ` | ` server/typescript/packages/metadata/src/source.ts ` |
15+ | Java | ` record DatabaseSource(DbLocation dbLocation, String jsonPath) ` + ` record DbLocation(String table, String id) ` | ` server/java/metadata/src/main/java/com/metaobjects/source/ ` |
16+ | C# | ` sealed record DatabaseSource(DbLocation DbLocation, string? JsonPath) ` + ` sealed record DbLocation(string Table, string Id) ` | ` server/csharp/MetaObjects/Source/ErrorSource.cs ` |
17+ | Python | ` @dataclass(frozen=True) DatabaseSource(db_location, json_path) ` + ` @dataclass(frozen=True) DbLocation(table, id) ` | ` server/python/src/metaobjects/source/error_source.py ` |
18+
19+ Per-port shape tests pin the envelope:
20+
21+ - TS: ` server/typescript/packages/metadata/test/source.test.ts ` — ` describe("ErrorSource — database variant (FR5e schema lock)") `
22+ - Java: ` server/java/metadata/src/test/java/com/metaobjects/source/DatabaseSourceShapeTest.java `
23+ - C#: ` server/csharp/MetaObjects.Conformance.Tests/Fr5eDatabaseSourceShapeTests.cs `
24+ - Python: ` server/python/tests/source/test_fr5e_database_source_shape.py `
25+
26+ A future database-source loader (FR-003 deliberately did NOT ship one — OMDB persists * user data* , not * metamodel* ) has a guaranteed-correct envelope target.
827
928## Goal
1029
11- When metadata is loaded from a database (instead of files), error envelopes report
12- the database location of the offending record:
30+ When metadata is loaded from a database (instead of files), error envelopes report the database location of the offending record:
1331
1432``` jsonc
1533{
@@ -26,33 +44,48 @@ the database location of the offending record:
2644}
2745```
2846
29- ## Why this exists now as a sketch
47+ ## Design lock (resolved 2026-05-27)
3048
31- ADR-0009 reserves ` format: "database" ` in the envelope so the schema is forward-stable.
32- FR5e is the placeholder for the implementation FR that lands alongside FR-003. No work
33- happens until FR-003 ships.
49+ The three open questions from the original sketch are settled:
3450
35- ## Open design questions (deferred)
51+ 1 . ** ` dbLocation ` shape: ` { table: string, id: string } ` — locked.**
52+ Composite primary keys are encoded into ` id ` as a single delimited string
53+ (e.g. ` "fld_abc123/currency" ` — row id + attr name joined with ` / ` ). Reasons:
54+ - Keeps the envelope dialect-neutral. Composite-key schemas vary by RDBMS;
55+ a richer ` dbLocation ` shape would bake one schema into the envelope.
56+ - Matches the pattern that JSON pointers / JSONPath already use for
57+ nested addressing.
58+ - Future loaders can pick the delimiter convention; the envelope just
59+ records the string.
3660
37- All of these wait for FR-003 to settle:
61+ 2 . ** Relationship between ` dbLocation ` and ` jsonPath ` : ` jsonPath ` is OPTIONAL.**
62+ When metadata is database-sourced, the JSONPath is a derived projection
63+ over the row's payload. ` dbLocation ` is the primary locator; ` jsonPath `
64+ adds precision when the offending node is nested within a row's
65+ payload (e.g. inside a JSONB blob of attributes).
3866
39- 1 . ** ` dbLocation ` shape** — is ` { table, id } ` enough, or do we need composite keys?
40- FR-003's schema dictates this.
41- 2 . ** Relationship between ` dbLocation ` and ` jsonPath ` ** — when metadata is database-
42- sourced, the JSONPath is a derived projection. Is ` jsonPath ` optional or required?
43- 3 . ** Multi-source metadata** — what if a single load aggregates from files + database?
44- The envelope discriminator allows it; do consumers need a ` format: "mixed" ` variant?
67+ 3 . ** Mixed-source metadata: NOT NEEDED in the envelope.**
68+ Each error carries the source format of the offending node, not the
69+ overall load. A mixed file+database load just produces errors with the
70+ appropriate per-error ` format ` . No ` format: "mixed" ` variant required.
4571
46- ## What FR5e WON'T do
72+ ## Out of scope
4773
48- - Define the OMDB schema or persistence semantics — that's FR-003.
49- - Define how database-sourced metadata is overlaid with file-sourced metadata — FR-003
50- again.
74+ - The OMDB metadata-table schema itself (which tables hold which metadata
75+ rows) — that's a separate FR when a real database-source loader is built.
76+ - The relationship between database-sourced and file-sourced metadata
77+ overlay/merge — same.
78+ - A reference database-source loader implementation — also separate.
5179
52- ## Open questions
80+ ## Implementing the loader (future, separate FR)
5381
54- To be settled during brainstorm when FR-003 nears delivery :
82+ When a database-source loader is built, the implementer must :
5583
56- 1 . Database location shape (table + id vs richer composite).
57- 2 . Mixed-source error attribution.
58- 3 . Whether to ship FR5e as part of FR-003 or as a follow-on.
84+ 1 . Emit ` DatabaseSource ` envelopes from every error / warning path.
85+ 2 . Use the existing parser/super-resolution/validation pipeline (same as the
86+ file-source loaders).
87+ 3 . Add a conformance fixture under ` fixtures/conformance/ ` that exercises a
88+ ` format: "database" ` error end-to-end (will require a synthetic test loader
89+ or an in-memory schema for the metaobjects tables).
90+ 4 . Decide overlay semantics with file-source metadata (will require a
91+ separate ADR — this is a real cross-language decision).
0 commit comments