Story: Import and export conventions without a document aggregate
Table of Contents
This page documents a story in Sprint 30, carried unfinished from Sprint 28 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
A conventions import and export carries each convention family as its own typed message. A new convention adds a family and does not grow a document aggregate. The staging and the atomic apply are merged (#3462 to #3485). What remains is the typed path: the ORE package, the export and the stage messages still use untyped JSON.
2. Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Parent sprint | Sprint 30 |
| Now | Not yet started. |
| Waiting on | Nothing. |
| Next | Break the story into tasks. |
| Last touched | 2026-11-08 |
3. Acceptance
- Each convention family is staged by a generated message that carries the family's value type.
- The transient conventions package holds typed rows and not JSON strings.
- The export reads each family through its generated list request at one instant.
ores.orehas no untypedrfl::Genericread of a convention.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Generate a typed view of the convention family registry | BACKLOG | Generate, beside the string registry, a compile-time list of every convention family's value type and protocol, so a caller can visit each family with its own types. | ||
| Stage each convention family as a typed message | BACKLOG | Replace the generic stage request, which carries a family name and the row as a JSON string, with one generated stage message per family that carries the family's own value type. | ||
| Export conventions through the typed family reads | BACKLOG | Read each convention family through its generated list request at one instant and for the run's party, in place of the untyped rfl::Generic reads in ores.ore. | ||
| Hold the conventions package as typed rows in ores.ore | BACKLOG | Keep the transient conventions package inside ores.ore as typed family rows, not JSON strings, so the mapper, the joins and the diff work on values. |
5. Decisions
- Pull requests merged in sprint 28 for this work, with no task to record them: #3462, #3465, #3467, #3469, #3474, #3475, #3481, #3482 and #3485. They stage a conventions import in two tables, apply it in one transaction, move the ORE path onto it, and rename the staging to bundle import. The story was carried with no task. The next owner should write the tasks and close the ones these PRs finished.
- 2026-11-02: the code drifted from the design into untyped data in three places. The stage message carries a family name and the row as a JSON string, where the design asks for one typed stage per family. The export reads each family through
rfl::Generic, with a hand-built request, the first array of the reply and a party filter in ores.ore, and a nullas_of. Inside ores.ore the package holds rows as JSON strings. The cause is that the registry is a table of strings, so only refdata's generated apply could dispatch on it. A typed view of the registry is the first task, and the other three build on it. A typed transient package inside ores.ore is allowed; one struct with a typed array per kind on the wire is not. - Goal and acceptance written on 2026-11-08 at sprint 30 start. They were still placeholders. They overlap the sqlgen and reflect-cpp story, which removes the same
rfl::Genericreads, so these two must be sequenced.