Context
Every owner answer that is a default value becomes a seed row (config-model section 6), so each product needs one seed pack with a stable format and a command that loads it without overwriting what a tenant changed. Wave 10 builtstackra seed-pack <product> and stackra new seed-pack in @stackra/cli with a closed list of eleven record kinds,
and left the seed runner (seedState, applySeed) to @stackra/database/node. Review round 2 (X2-36) found that a
closed kind list in the CLI is code deciding what configuration may exist, and that half the record kinds named since
2026-10-25 were missing from it. stackra new covers packages, services and seed packs; app kinds still use
pnpm new.
Decision
- One pack per product. A product keeps
seed-pack:<product>inseed-packs/<product>/of its repository: aseed-pack.yamlheader (key,product, a semanticversion) and one YAML document per record underprofiles/minimal/,profiles/demo/andprofiles/test/. A document haskind, the recordkeyandrows; every row has anidand theanswerid it encodes (COM-160). A row without an answer id is refused. - Record kinds are a registry. A record kind is registered by the package that owns it, with a schema and a
validator, and the CLI reads the registry; it holds no list of its own. The first kinds are those of the wave 10
list (settings, rule-set, workflow-template, studio-template, role-template, industry-template, plan-catalogue,
price-list, offer, connector-catalogue, brand-kit) plus the kinds the answers already use: rate-card,
fee-schedule, launch-gate, module-availability, product-availability, device-catalogue, tenant-kind, region-map,
os-company, notification-category, data-class, provider-category, perk, payroll mapping and importer profile. An
unknown kind is
seed_kind_unknown. - Profiles layer.
minimalis a new tenant’s defaults;demoandtestloadminimalfirst and add their own records. One record key seeded twice across a profile’s layers is refused (seed_record_duplicate); a demo that needs another value seeds its own record. - The command.
stackra seed-pack <product> --checkvalidates the header, every record against its kind’s schema, the answer ids, and (with X2-19) every market pack section the product ships, against the section schemas of@stackra/market-packs, including that an overlay floor is not looser than its parent. Without--check, the command plans by content hash and writes through the member’sSeedRunner(seedState,applySeedin@stackra/database/node) only new records and seed-owned records whose hash changed. - Product defaults, never tenant values. The runner writes the product-default layer (0363 decision 5). A
tenant’s edit is a tenant-layer value or a tenant-owned copy, so a new seed version only changes the default
underneath. Ownership is per record (
owner: seed | tenant), because a tenant edits a template by copying it. - No
--tenantoption. The CLI never seeds a tenant. A new sandbox receives live configuration plus thedemoprofile through the OS sandbox workflow (0359 decision 11), which calls the same runner for that sandbox. - Seeded automations run as a principal. A seeded automation is owned by a standing service principal
seed:<product>(0153); Figentra’s own seeds skip the dry run of 0122, and a tenant edit re-owns its copy to the editor and runs the dry run (X2-38). stackra newtemplate set.stackra new <kind> <name>writes the v3 shapes of 0294:package(--category),service(--area) andseed-pack. App kinds (console, mobile, desktop, docs) move tostackra newas their v3 templates land; until then they stay withpnpm new. Templates are code in@stackra/cli/node; they hold no business value.- Values. Everything in a seed pack is seed data; market-pack sections are pack data and are only checked here. Settings rows seed the product-default layer of settings; rule-set and workflow-template records seed rule sets and workflows. The command itself holds none of them.
Consequences
- A changed owner answer is one changed row, found by its answer id.
- A package that adds a record kind registers it; no CLI release is needed.
stackra seed-packfails without--checkuntil@stackra/database/nodeexports the runner.
Enforcement
planned —stackra seed-pack <product> --check in each product’s CI; the refusal codes are seed_pack_header,
seed_profile_unknown, seed_kind_unknown, seed_record_key_missing, seed_record_duplicate,
seed_row_id_missing, seed_row_duplicate and seed_row_answer_missing. The kind registry replaces
packages/developer/cli/src/node/constants/seed-record-kinds.constant.ts.
Supersedes and sources
Supersedes: none. Sources:notes/handover/build-wave10-2026-10-25.md (CLI builder, questions 2 to 5 and 8; rules and
workflow builder, question 1); notes/handover/config-model.md section 6; notes/handover/review-round-2/cross.md
(X2-19, X2-36, X2-38); packages/developer/cli/README.md (seed packs).