@wildo-ai/platform-core-shared 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/resources/resources-operations.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/core/resources/resources-relationships.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.d.ts +49 -4
- package/dist/esm/runtime/application-backend-env.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.js +48 -1
- package/dist/esm/runtime/application-backend-env.contracts.js.map +1 -1
- package/dist/esm/runtime/http-server-env.contracts.d.ts +46 -0
- package/dist/esm/runtime/http-server-env.contracts.d.ts.map +1 -0
- package/dist/esm/runtime/http-server-env.contracts.js +55 -0
- package/dist/esm/runtime/http-server-env.contracts.js.map +1 -0
- package/dist/esm/runtime/runtime-topology.contracts.d.ts +0 -4
- package/dist/esm/runtime/runtime-topology.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/runtime-topology.contracts.js +0 -12
- package/dist/esm/runtime/runtime-topology.contracts.js.map +1 -1
- package/dist/esm/security/authorizations/roles.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts +166 -70
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts +166 -70
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js +2 -2
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts +21 -10
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts +21 -10
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js +26 -28
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.d.ts +29 -0
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.js +58 -0
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.d.ts +13 -0
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js +441 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts +279 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js +303 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts +199 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js +185 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.d.ts +49 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.js +42 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts +461 -11
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js +509 -6
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts +1102 -12
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js +1520 -19
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts +123 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js +168 -0
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts +229 -9
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js +2 -2
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts +18 -3
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js +35 -7
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -13
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.d.ts +0 -98
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.d.ts.map +0 -1
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.js +0 -86
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.js.map +0 -1
|
@@ -215,6 +215,16 @@ export const Workbench_DomainResource_Schema = z.object({
|
|
|
215
215
|
isUnimplemented: z.boolean(),
|
|
216
216
|
isDisabled: z.boolean(),
|
|
217
217
|
requiresStepUpAuthentication: z.boolean(),
|
|
218
|
+
/**
|
|
219
|
+
* The variant's `idempotencyKey` declaration (#535) — `accepted` or `required` — or null when it takes no key. A plain
|
|
220
|
+
* string for the same reason as the other vocabularies here: the observed application may run another engine revision.
|
|
221
|
+
*/
|
|
222
|
+
idempotencyKey: z.string().min(1).nullable(),
|
|
223
|
+
/**
|
|
224
|
+
* The action the variant's `submissionChallenge` declaration binds a caller's captcha token to (#1985), or null when a
|
|
225
|
+
* caller who is not signed in answers no challenge. A plain string: an application names its own actions.
|
|
226
|
+
*/
|
|
227
|
+
submissionChallengeAction: z.string().min(1).nullable(),
|
|
218
228
|
admitsCrossTenantPlatformAdministration: z.boolean(),
|
|
219
229
|
auditableEventType: z.string().min(1).nullable(),
|
|
220
230
|
isMcpExposed: z.boolean(),
|
|
@@ -351,6 +361,15 @@ export var WorkbenchSpecificationArtifactState;
|
|
|
351
361
|
*/
|
|
352
362
|
WorkbenchSpecificationArtifactState["NOT_LANDED"] = "not_landed";
|
|
353
363
|
})(WorkbenchSpecificationArtifactState || (WorkbenchSpecificationArtifactState = {}));
|
|
364
|
+
/**
|
|
365
|
+
* One WARNING the family's validator reports on the landed content: where it sits in the artifact
|
|
366
|
+
* (`path`, the validator's own dotted locator) and what it says (`message`, the validator's words).
|
|
367
|
+
* A warning is authoring drift that does not invalidate the artifact — see `warnCount`.
|
|
368
|
+
*/
|
|
369
|
+
export const Workbench_SpecificationArtifactWarning_Schema = z.object({
|
|
370
|
+
path: z.string(),
|
|
371
|
+
message: z.string(),
|
|
372
|
+
});
|
|
354
373
|
/**
|
|
355
374
|
* ONE application-specification family, projected for a human reviewer.
|
|
356
375
|
*
|
|
@@ -367,7 +386,7 @@ export var WorkbenchSpecificationArtifactState;
|
|
|
367
386
|
*
|
|
368
387
|
* ## Why the heavy fields are NOT summary fields
|
|
369
388
|
*
|
|
370
|
-
* `document`, `issues`, `decisionRecord` and `diagram` are excluded from the summary by omission, so
|
|
389
|
+
* `document`, `issues`, `warnings`, `decisionRecord` and `diagram` are excluded from the summary by omission, so
|
|
371
390
|
* a list carries the INDEX while a detail page carries the documents. One derivation still computes
|
|
372
391
|
* all of them either way — this bounds the RESPONSE, not the work.
|
|
373
392
|
*
|
|
@@ -406,9 +425,9 @@ export const Workbench_SpecificationArtifact_Schema = z.object({
|
|
|
406
425
|
*/
|
|
407
426
|
contentSummary: z.string().nullable().isSummaryField(),
|
|
408
427
|
/** The question this family answers, which is the axis the list groups by. */
|
|
409
|
-
concern: z.enum(WorkbenchSpecificationArtifactConcern).isSummaryField(),
|
|
428
|
+
concern: z.enum(WorkbenchSpecificationArtifactConcern).systemEnum('WorkbenchSpecificationArtifactConcern').isSummaryField(),
|
|
410
429
|
/** Landed and valid, landed and invalid, or not landed at all. */
|
|
411
|
-
state: z.enum(WorkbenchSpecificationArtifactState).isSummaryField(),
|
|
430
|
+
state: z.enum(WorkbenchSpecificationArtifactState).systemEnum('WorkbenchSpecificationArtifactState').isSummaryField(),
|
|
412
431
|
/** The `_core` contract the family's content must satisfy, verbatim from the semantic authority. */
|
|
413
432
|
schemaRef: z.string().min(1),
|
|
414
433
|
/**
|
|
@@ -440,11 +459,11 @@ export const Workbench_SpecificationArtifact_Schema = z.object({
|
|
|
440
459
|
*
|
|
441
460
|
* ## Why the raw value rides beside its rendering
|
|
442
461
|
*
|
|
443
|
-
* The per-family
|
|
462
|
+
* The per-family presentations (workbench `artifact-presentation/`) render EDITORIALLY — an ICP
|
|
444
463
|
* card, a requirement with its acceptance criteria, a placement decision with its rationale — and
|
|
445
|
-
* an editorial
|
|
446
|
-
* below stays: it is the structural fallback every family keeps behind the
|
|
447
|
-
* boundary, and the whole rendering for a family
|
|
464
|
+
* an editorial arrangement needs the VALUE, not a markdown projection of it. The markdown
|
|
465
|
+
* `document` below stays: it is the structural fallback every family keeps behind the content
|
|
466
|
+
* error boundary, and the whole rendering for a family this build's vocabulary does not know.
|
|
448
467
|
*
|
|
449
468
|
* ## Untyped HERE, typed at the EDGE — a measured decision, not an omission
|
|
450
469
|
*
|
|
@@ -478,6 +497,15 @@ export const Workbench_SpecificationArtifact_Schema = z.object({
|
|
|
478
497
|
* only the signal to come and look.
|
|
479
498
|
*/
|
|
480
499
|
issues: z.string().nullable(),
|
|
500
|
+
/**
|
|
501
|
+
* Every WARNING the validator reports, structured, one entry per finding — `[]` when there are
|
|
502
|
+
* none or the family has not landed. `warnCount` is its length.
|
|
503
|
+
*
|
|
504
|
+
* Structured rather than folded into `issues` (which carries the ERRORS) so the page names them in
|
|
505
|
+
* its own authored words: until 2026-09-25 only the count left the companion, and the page could say
|
|
506
|
+
* "25 warnings" and then had to send the reader to the file to learn what they were.
|
|
507
|
+
*/
|
|
508
|
+
warnings: z.array(Workbench_SpecificationArtifactWarning_Schema),
|
|
481
509
|
/**
|
|
482
510
|
* `DECISIONS.md` committed beside the family, verbatim, or `null` when there is none.
|
|
483
511
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workbench-resources.custom.shared.schemas.js","sourceRoot":"","sources":["../../../src/workbench/workbench-resources.custom.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { initZodDecorators } from '@wildo-ai/zod-decorators';\n\ninitZodDecorators(z);\n\n\n/**\n * One relationship, as it rides on BOTH resources it joins.\n *\n * ## Why an edge appears on two rows rather than on one\n *\n * A relationship genuinely IS a property of both resources — \"what is `deals` related to?\" is a\n * question about `deals` and about everything `deals` touches — so carrying it on both is a\n * statement of what it means, not an encoding chosen to fit a row shape. Hanging every edge off one\n * arbitrarily-chosen endpoint would be the encoding, and the choice would have to be re-derived by\n * every reader.\n *\n * The consumer draws each edge once, keyed by {@link relationshipId}. The duplication costs one extra\n * copy of a small object per edge and buys a row that is complete on its own.\n *\n * ## Why the vocabularies are plain strings\n *\n * These values cross a subprocess boundary from the OBSERVED application's registry, which may be\n * built against a different engine revision than the workbench. Binding `nature` or the cardinalities to the engine enums would make a\n * row the observed application can legitimately produce unparseable here — the workbench refusing to\n * show exactly the drift it exists to reveal.\n */\nexport const Workbench_DomainResourceRelationship_Schema = z.object({\n /**\n * Stable identity for ONE edge within this projection, composed from every field carried about it.\n *\n * NOT the `resourceType1__resourceType2__foreignKeyField` triple the retired\n * `workbenchResourceRelationships` resource addressed a row by: that triple is not total here,\n * because a MANY-to-MANY edge carries\n * `jointResourceType` and no `foreignKeyField`. Two edges agreeing on every field below are\n * indistinguishable to a graph, so merging them loses nothing a reader could have seen.\n */\n relationshipId: z.string().min(1),\n resourceType1: z.string().min(1),\n resourceType2: z.string().min(1),\n cardinality1: z.string().min(1),\n cardinality2: z.string().min(1),\n /**\n * `composition`, `reference` or `association` — every member `RelationshipNature` declares — kept as\n * a plain string for the drift-tolerance reason above, not because a fourth one exists today.\n */\n nature: z.string().min(1),\n /** The field carrying the join. Absent on a junction-backed MANY-to-MANY, which has no FK column. */\n foreignKeyField: z.string().min(1).nullable(),\n /**\n * Which side's rows CARRY the foreign key — the direction an arrow must point.\n *\n * Resolved by the framework's own `resolveForeignKeyHolderResourceType`, from CARDINALITY, never\n * from declaration order: `(TODOS, USERS, MANY, ONE, { foreignKeyField })` is a valid child-first\n * declaration that puts the referenced resource in `resourceType2`, so a consumer reading position\n * draws half its arrows backwards.\n */\n foreignKeyHolderResourceType: z.string().min(1),\n /** The junction resource of a MANY-to-MANY, which the framework requires such an edge to name. */\n jointResourceType: z.string().min(1).nullable(),\n /** Whether this edge is the structural ownership anchor giving `resourceType2` its scope. */\n isPrimaryScope: z.boolean(),\n /**\n * Whether the edge is DECLARED BUT INACTIVE.\n *\n * The one field here whose absence made the graph WRONG rather than thinner: a disabled edge\n * constrains nothing at runtime, so drawing it like a live one tells a reader the application has\n * a relationship it does not have. Carried even though the dogfood application disables none\n * (measured 2026-08-31: 0 of 16) — a field that is uniformly `false` today is exactly the one that\n * silently misleads the first time it is not.\n */\n isDisabled: z.boolean(),\n /**\n * How a caller reaches rows on the far side — `requires_context`, `standalone`, and whatever else\n * the observed application's engine revision declares.\n *\n * A plain string for the same drift-tolerance reason `nature` is one.\n */\n accessScopeStrategy: z.string().min(1).nullable(),\n /** Whether the parent endpoint is `mandatory` or `optional` for the child's addressing. */\n parentResourceRequirement: z.string().min(1).nullable(),\n /**\n * WHICH resource this edge anchors scope to, when it anchors one.\n *\n * Not derivable from {@link isPrimaryScope}, which says only THAT it anchors. On an edge whose\n * endpoints are both scoped, the two answer different questions.\n */\n primaryScope: z.string().min(1).nullable(),\n /** Whether a cycle through this edge is permitted — a graph-shape fact a graph should be able to show. */\n allowCycle: z.boolean(),\n});\n\nexport type Workbench_DomainResourceRelationship = z.infer<typeof Workbench_DomainResourceRelationship_Schema>;\n\n/**\n * ONE resource of the observed application's domain model — node, module membership, specification\n * and edges in a single row.\n *\n * ## Why every field is a summary field\n *\n * A LIST renders the SUMMARY projection, and this resource's list IS its whole purpose: the graph\n * consumes the collection. A field left out of the summary is a field the graph cannot draw, and the\n * omission is silent — the row arrives, the field is simply absent. So the summary here is the full\n * row by design rather than by neglect.\n *\n * ## Why this is one row per RESOURCE rather than one row per module or one row for the graph\n *\n * Edges are resource-to-resource. A module-per-node projection would have to AGGREGATE them, which\n * destroys precisely the meanings the framework refuses to merge — nature, cardinality, foreign-key\n * direction — and a graph that draws every edge as one grey line has lost information the flat table\n * at least preserved.\n */\nexport const Workbench_DomainResource_Schema = z.object({\n /**\n * Composed by the introspection source from the binding's `identityFields` (`['resourceType']`).\n *\n * `.isSummaryField()` on the IDENTITY field is load-bearing rather than cosmetic: the projection a\n * list renders is the summary, and a row with no id is a row nothing can address — the failure that\n * made every relationship row unclickable before its id was marked.\n */\n workbenchDomainResourceId: z.string().min(1).isPrimaryKey().isSummaryField(),\n resourceType: z.string().min(1).isSummaryField(),\n /**\n * The module that registers this resource, or `null`.\n *\n * `null` is a FACT, not a gap: no module of the observed application owns this resource, which is\n * true of every ENGINE resource — and an application merges all of them, since `initializeResources`\n * applies the engine's core factory map unconditionally and both registries merge it. They are\n * carried rather than dropped because they are part of the running application, and because an edge\n * to the resource that gives a row its tenant scope is the most load-bearing edge in the graph.\n *\n * No `origin` field restates this. The absence of a module IS the distinction, and a second field\n * saying the same thing is a second thing that can disagree with the first.\n */\n moduleId: z.string().min(1).isSummaryField().nullable(),\n /** `domain` or `engine` — the kind the owning module declares, when there is one. */\n moduleKind: z.string().min(1).isSummaryField().nullable(),\n /**\n * Which part of its owner this resource belongs to — a SECOND grouping axis, under the module.\n *\n * Sourced from `ResourceSpecificationConfig.subDomain`. For engine resources that is the closed\n * `EngineResourceSubDomain` vocabulary (`auth`, `billing`, `users`, …), which exists because the\n * engine's 85 resources otherwise arrive as one flat set and every surface that has to present them\n * invents a grouping of its own.\n *\n * A plain `string` here rather than that enum, and deliberately: this schema is shared by a\n * workbench that observes an application whose own sub-domains it cannot enumerate. Pinning the\n * engine's vocabulary here would make an application's value invalid at the wire.\n *\n * `null` means the resource specification declares none — an application resource today, or an engine\n * resource with no spec at all. A consumer grouping by this must carry an \"unclassified\" bucket and\n * say so, rather than folding those rows into a real group.\n */\n subDomain: z.string().min(1).isSummaryField().nullable(),\n /**\n * Every field of the materialized `mainSchema`, with everything the framework knows about it.\n *\n * This replaced a bare `fieldNames: string[]`, whose JSDoc argued that \"a domain-model panel\n * answers what a resource HOLDS\" and that per-field extraction \"belongs to `resource-specifications`\".\n * The premise was right and the conclusion aged badly: a NAME answers \"does this field exist\",\n * which the node already implies by counting them, and a reader who opens a resource wants what\n * the field IS. The cost was then MEASURED rather than assumed — 715 fields across the 82 engine\n * resources extract to 264 KB, a fraction of what the relationship edges already cost — so the\n * reason to withhold it was gone.\n *\n * `params`, `derived` and `origin` are OPAQUE records on purpose. They are the extractor's own\n * output — authored spec prose, framework-derived structure, base-vs-variant provenance — and each\n * is an open shape that grows with the decorators. Restating them field by field here would make\n * this schema a second, always-lagging copy of a contract `@wildo-ai/saas-specifications` owns;\n * a consumer that needs one reads it through that package's type.\n */\n fields: z.array(z.object({\n fieldName: z.string().min(1),\n /** Which `{primitive}Spec()` decorator carried the authored prose, when one did. */\n specDecorator: z.string().min(1).nullable(),\n params: z.record(z.string(), z.unknown()).nullable(),\n derived: z.record(z.string(), z.unknown()).nullable(),\n origin: z.record(z.string(), z.unknown()).nullable(),\n /**\n * The field's DECORATOR record, as the schema declares it — beside `derived`, which is the\n * extractor's interpretation of it.\n *\n * It carries what the interpretation drops: `isSummaryField`, `isHidden`, `excludeFromCreate` /\n * `excludeFromUpdate`, `dataCategories`, and the index / unique / primary-key trio.\n *\n * It does NOT carry `*.ui-behavior.tsx` configuration, and that is a reachability limit rather\n * than an omission: those decorators are applied by a FRONTEND module the companion never loads,\n * because the subprocess resolves `library`, `specifications` and `service` targets and there is\n * no frontend one. Measured on the engine's resources — zero UI keys present.\n */\n metadata: z.record(z.string(), z.unknown()).nullable(),\n })).isSummaryField(),\n /**\n * Every operation the resource declares, projected to what a READER needs.\n *\n * Never the DTOs. A materialized operation carries six Zod schemas — request, response, summary,\n * context, internal, repository — each serializing to tens of kilobytes, so carrying the operation\n * objects would put megabytes on the wire to say which verbs exist. What is here is the identity,\n * the variant, the authorization and the flags that change what the operation DOES.\n *\n * An EMPTY `roles` array is a real answer — no role gate on that variant — and not a gap.\n */\n operations: z.array(z.object({\n operationIdentifier: z.string().min(1),\n /** The TRANSPORT kind: `api_call`, `internal_call`, `repository_only`, … */\n variantType: z.string().min(1).nullable(),\n /**\n * WHICH variant of that transport — `admin`, `summary`, `context` — or `null` for the default.\n *\n * The missing half of an operation's IDENTITY, and its absence was a defect rather than missing\n * detail: `organizations` declares four operations that are all `read` × `api_call`, separated\n * only by this key, and across the engine's core map 133 of 794 operations collided on the pair\n * without it.\n */\n variantKey: z.string().min(1).nullable(),\n /** For a CUSTOM operation, the core verb it behaves like. `null` for a core operation. */\n resourceOperationLike: z.string().min(1).nullable(),\n isDefault: z.boolean(),\n roles: z.array(z.string()),\n riskLevel: z.string().min(1).nullable(),\n isUnimplemented: z.boolean(),\n isDisabled: z.boolean(),\n requiresStepUpAuthentication: z.boolean(),\n admitsCrossTenantPlatformAdministration: z.boolean(),\n auditableEventType: z.string().min(1).nullable(),\n isMcpExposed: z.boolean(),\n requiredFeatures: z.array(z.string()),\n /**\n * Everything else the operation declares — HTTP verb, runtime mode, bulk and API-key posture,\n * notification fan-out, custom-implementation modes, authoritative fields.\n *\n * A DENY LIST over the operation's own keys on the producing side, for the same reason `advanced`\n * is, and this is the one that proved the argument: a hand-picked set of twelve fields shipped\n * without `variantKey`, `httpVerb`, `isBulkOperation` or `serviceRuntimeMode`. The six DTO\n * schemas are excluded by name — each serializes to tens of kilobytes.\n */\n attributes: z.record(z.string(), z.unknown()),\n /**\n * The authored specification for this operation, keyed by `operationIdentifier` — so every\n * VARIANT of one verb carries the same entry, which is what the specification describes.\n *\n * `null` means the specification does not mention the operation: a gap a reader can act on.\n */\n specification: z.record(z.string(), z.unknown()).nullable(),\n /** The authored `frontend.views` overlay for this operation, when there is one. */\n view: z.record(z.string(), z.unknown()).nullable(),\n })).isSummaryField(),\n /**\n * The operations for which the resource specification declares a FRONTEND view overlay (`frontend.views`).\n *\n * Refs only. The entries are authoring prose about how an operation surfaces, which belongs to a\n * specification reader; what a domain-model panel can act on is which operations have an authored\n * view and — by difference with `operations` — which do not.\n */\n viewRefs: z.array(z.string()).isSummaryField(),\n /**\n * The configuration facts that are neither prose nor structure — persistence, policy, bindings.\n *\n * Everything on the resource's `ResourceConfiguration` that decides how it BEHAVES rather than what\n * it holds: which database it lives in, whether it is a system resource, its retention,\n * transposition, portability and data-subject policies, its HTTP and introspection bindings.\n *\n * An OPAQUE record, and deliberately so. The producer builds it by DENY list over the\n * configuration's own keys rather than by enumerating the ones that exist today, because\n * `ResourceConfiguration` has grown several of these fields in as many months and an enumeration\n * reports the subset its author knew about. Typing it here would put that enumeration back.\n */\n advanced: z.record(z.string(), z.unknown()).isSummaryField(),\n /**\n * The authored specification's PROSE, or `null` when this resource has none.\n *\n * It rides in the row rather than being fetched on selection because a per-selection fetch is not\n * cheaper: `deriveRows` has no per-row path, so an addressed READ derives the WHOLE set and filters\n * it afterwards. \"Fetch the specification when a node is clicked\" would therefore be a second full\n * derivation of the entire application.\n */\n specification: z.object({\n /** Why this resource exists in the domain. */\n purpose: z.string(),\n /** The functional role it plays inside the business architecture. */\n businessRole: z.string(),\n /** How it evolves over time. Optional in the specification contract, so nullable here. */\n lifecycleRole: z.string().nullable(),\n /** Domain caveats not encoded structurally elsewhere. */\n businessConstraints: z.array(z.string()),\n }).isSummaryField().nullable(),\n /** Every relationship this resource participates in, on either side. */\n relationships: z.array(Workbench_DomainResourceRelationship_Schema).isSummaryField(),\n});\n\nexport type Workbench_DomainResource = z.infer<typeof Workbench_DomainResource_Schema>;\n\n/**\n * ONE FIELD of a domain resource — named so a consumer can hold one without re-deriving its type.\n *\n * Indexed off the row rather than declared separately, because the schema is the one authority for\n * the shape and a second declaration is a second thing that can drift from it.\n */\nexport type Workbench_DomainResourceField = Workbench_DomainResource['fields'][number];\n\n/** ONE OPERATION of a domain resource — indexed off the row, for the same reason. */\nexport type Workbench_DomainResourceOperation = Workbench_DomainResource['operations'][number];\n\n/**\n * The QUESTION a specification family answers — the axis the workbench groups them by.\n *\n * ## Why the families are grouped at all\n *\n * Fifteen rows in one undifferentiated list is a directory, not a review surface. A creator opening\n * the workbench is not looking for \"the `document-release-policy` family\"; they are looking for what\n * was decided about who this product is for, or about what it must promise. Grouping by the question\n * answered is what makes the list navigable without inventing twelve destinations.\n *\n * ## Why this is a display vocabulary and not a property of the family\n *\n * `ApplicationSpecificationFamilySemanticSchemaRef` names what a family MEANS and what validates it.\n * Nothing in the runtime branches on the concern below — it exists so a reader can find a row. Adding\n * it to the semantic authority would put a workbench presentation choice inside the contract the\n * journey lands artifacts against.\n *\n * The family → concern mapping deliberately lives with the projection that derives it (the\n * companion's `specification-artifacts` behavior), beside the semantic authority it must stay\n * exhaustive over, rather than here where the authority is not reachable.\n */\nexport enum WorkbenchSpecificationArtifactConcern {\n /** Why the product exists and who it is for — `vision-brief`, `market-snapshot`. */\n INTENT = 'intent',\n /** What it must do and what it costs — `requirements`, `feature-drafts`, `business-model`. */\n SCOPE = 'scope',\n /** How and when it gets built — `domain-plan`, `build-plan`, `roadmap`, `placement-plan`. */\n DELIVERY = 'delivery',\n /** How it presents itself — `brand-brief`. */\n IDENTITY = 'identity',\n /** What it must promise and publish — the assurance and governed-document families. */\n OBLIGATIONS = 'obligations',\n /**\n * A family the workbench has not been taught to group.\n *\n * A named member rather than a throw, and rather than silence. The population is derived from the\n * semantic authority, so a family added there arrives here with no classification — and the two\n * alternatives are both worse than a visible bucket: refusing the derivation would blank the whole\n * page over one unmapped row, and defaulting into a real concern would file the new family\n * somewhere plausible and wrong, which nobody would notice.\n *\n * A companion test asserts this member is currently UNUSED, so it stays a signal rather than\n * becoming a habit.\n */\n UNCLASSIFIED = 'unclassified',\n}\n\n/**\n * Whether a family has landed, and whether what landed still validates.\n *\n * THREE states, not two, because \"not landed\" and \"landed but invalid\" are the opposite instructions\n * to a reviewer: the first is work the journey has not done, the second is work it did that no longer\n * holds. A boolean `isValid` would report both as `false`.\n */\nexport enum WorkbenchSpecificationArtifactState {\n /** The family is exported by the application and its `_core` validator reports no error. */\n LANDED_VALID = 'landed_valid',\n /** The family is exported and its `_core` validator reports at least one ERROR-severity issue. */\n LANDED_INVALID = 'landed_invalid',\n /**\n * The application exports nothing for this family.\n *\n * Reported as a ROW rather than omitted — the same call `definition-specifications.behavior.ts`\n * makes for the same reason: *\"an omitted row and a family that does not exist would look the same\n * to the reader.\"* On a fresh application an empty list would say nothing; fifteen NOT_LANDED rows\n * say what the journey has left to produce.\n */\n NOT_LANDED = 'not_landed',\n}\n\n/**\n * ONE application-specification family, projected for a human reviewer.\n *\n * ## Why the prose fields are markdown strings\n *\n * `StringDisplayMode.MARKDOWN` renders GFM through the framework's own display chrome, which is what\n * lets headings, lists and paragraphs survive into the page. The alternative — modelling each\n * family's shape as nested schema fields — would have to be done fifteen times, would freeze twelve\n * `_core` contracts into this projection, and would still render as a form rather than as a document.\n *\n * The rendering is an OUTLINE, never a table. That is the acceptance criterion this resource exists\n * to satisfy: these artifacts are prose-heavy and their value is in the rationale, so a projection\n * that put them in columns would destroy exactly what makes them worth reviewing.\n *\n * ## Why the heavy fields are NOT summary fields\n *\n * `document`, `issues`, `decisionRecord` and `diagram` are excluded from the summary by omission, so\n * a list carries the INDEX while a detail page carries the documents. One derivation still computes\n * all of them either way — this bounds the RESPONSE, not the work.\n *\n * Which variant a caller gets matters, and is easy to state wrongly: the LIST operation's DEFAULT\n * variant answers the full row, and it is the operation's `summary` variant that applies this\n * projection. Measured against the live wonder-crm companion, 2026-08-31:\n * `GET /api/v1/workbench-specification-artifacts` → **149,089 B**, and\n * `…/workbench-specification-artifacts/summary` → **3,654 B** carrying the eight fields marked\n * below. A list layout renders the summary variant — which is also why the addressing field must be\n * marked, or every row in that list is unclickable.\n */\nexport const Workbench_SpecificationArtifact_Schema = z.object({\n /**\n * The family id — `vision-brief`, `market-snapshot`, `compliance-program`.\n *\n * The source's own key, marked `.isSummaryField()` because a list row with no id is a row nothing\n * can address: the summary projection is what a click reads the target from.\n */\n family: z.string().min(1).isPrimaryKey().isSummaryField(),\n /** The family's name in a creator's words — `Vision`, `Market`, `Assurance programme`. */\n title: z.string().min(1).isSummaryField(),\n /**\n * What this family IS, in one sentence a creator recognizes — static per family, present whether\n * or not anything landed. This is the summary card's subtitle: a card reading only\n * \"Governed-document drafts · Not landed\" tells a reader nothing they can act on; \"The drafts of\n * the public documents this product must publish\" does.\n */\n description: z.string().min(1).isSummaryField(),\n /**\n * A one-line PULSE of the landed content — `\"3 ICPs · 5 personas · 2 positionings\"`, the vision's\n * own one-liner — or `null` when the family has not landed.\n *\n * Derived server-side from the RAW value so the list answers \"how much is in there\" without any\n * client downloading fifteen full documents. It is a COUNT-and-headline summary, never a\n * truncation of prose: a clipped sentence reads as an accident, a count reads as an answer.\n */\n contentSummary: z.string().nullable().isSummaryField(),\n /** The question this family answers, which is the axis the list groups by. */\n concern: z.enum(WorkbenchSpecificationArtifactConcern).isSummaryField(),\n /** Landed and valid, landed and invalid, or not landed at all. */\n state: z.enum(WorkbenchSpecificationArtifactState).isSummaryField(),\n /** The `_core` contract the family's content must satisfy, verbatim from the semantic authority. */\n schemaRef: z.string().min(1),\n /**\n * Where the family's file lives, relative to the application root — the file a reader opens when\n * the rendering is not enough.\n *\n * `null` when this runtime places no file for the family. A placement and a RENDER PROFILE are\n * different things (`playbook-output-landing-target`), and only the placement is asked for here.\n */\n sourcePath: z.string().min(1).nullable().isSummaryField(),\n /** ERROR-severity issues the family's own validator reports on the landed content, right now. */\n errorCount: z.number().int().nonnegative().isSummaryField(),\n /** WARN-severity issues — authoring drift that does not invalidate the artifact. */\n warnCount: z.number().int().nonnegative().isSummaryField(),\n /**\n * Every playbook whose declared `outputs[].family` is this family.\n *\n * This is the durable half of \"what produced it\": a fact about the compiled catalog, in git, true\n * whether or not any run's state survives. A link to the RUN that produced this particular value\n * was deliberately rejected — runs, traces and the write register are a per-run cache under\n * `one-source-of-truth.md` Rule 5, so a durable artifact pointing into deletable state is dangling\n * by design. The link runs the other way: a run may name what it wrote.\n *\n * Empty for a family no playbook produces — which is a finding, not a gap.\n */\n producedByPlaybookRefs: z.array(z.string()).isSummaryField(),\n /**\n * The landed family value, RAW — exactly the object the specifications package exports.\n *\n * ## Why the raw value rides beside its rendering\n *\n * The per-family display templates (workbench `artifact-templates/`) render EDITORIALLY — an ICP\n * card, a requirement with its acceptance criteria, a placement decision with its rationale — and\n * an editorial template needs the VALUE, not a markdown projection of it. The markdown `document`\n * below stays: it is the structural fallback every family keeps behind the template error\n * boundary, and the whole rendering for a family no template covers yet.\n *\n * ## Untyped HERE, typed at the EDGE — a measured decision, not an omission\n *\n * The typed `_core` snapshot schemas live in `@wildo-ai/saas-specifications`, which depends on\n * `saas-frontend-lib` AND `saas-backend-lib` (its package.json) — while this package is the\n * platform's light contracts-only spine (`platform/CLAUDE.md`). Typing this field would drag the\n * whole engine into every consumer of this package for a shape only two consumers read. The two\n * readers type it themselves: the companion behavior validates through the semantic authority\n * before emitting, and the workbench templates narrow via TYPE-ONLY imports (erased at compile,\n * zero runtime dependency). Recorded with alternatives in\n * `.claude/plans/workbench-product-artifacts-ux-analysis.md` (D1).\n *\n * Deliberately NOT a summary field: the LIST carries the index, and this is the heaviest thing a\n * row owns. Emitted from the RAW landed value — never from a validator's parsed output, whose\n * schema `.default()`s would inject content the author never wrote.\n */\n content: z.record(z.string(), z.unknown()).nullable(),\n /**\n * The artifact rendered as a document, or `null` when the family has not landed.\n *\n * Produced by `renderSpecificationFamilyReviewDocument` — an outline over the landed value, not a\n * prompt block. The prompt renderers (`market-render-prompt`, `brand-render-prompt`) read the same\n * content for a language model and must never be reused here.\n */\n document: z.string().nullable(),\n /**\n * The validator's own findings, rendered for a reader, or `null` when there are none.\n *\n * Carried as content rather than as counts alone because a reviewer deciding whether to accept an\n * artifact needs to see WHICH rule failed and where, and the counts beside them in the list are\n * only the signal to come and look.\n */\n issues: z.string().nullable(),\n /**\n * `DECISIONS.md` committed beside the family, verbatim, or `null` when there is none.\n *\n * The strongest provenance this surface has: it names the playbook that produced the artifact and,\n * more importantly, records every question the creator was asked — including the ones they did NOT\n * answer, where \"the derivation chose for itself\". A run that asked nothing writes no such file, so\n * `null` here means \"no clarification was recorded\", never \"no clarification happened\".\n */\n decisionRecord: z.string().nullable(),\n /**\n * `DIAGRAM.md` committed beside the family, verbatim, or `null`.\n *\n * Three families have one today (`domain-plan`, `build-plan`, `roadmap`). It is surfaced rather\n * than re-derived: the diagram is already a committed output of the family, regenerated on every\n * landing, and rendering a second picture here would be a second thing that can disagree with it.\n */\n diagram: z.string().nullable(),\n});\n\nexport type Workbench_SpecificationArtifact = z.infer<typeof Workbench_SpecificationArtifact_Schema>;\n"]}
|
|
1
|
+
{"version":3,"file":"workbench-resources.custom.shared.schemas.js","sourceRoot":"","sources":["../../../../src/workbench/workbench-resources.custom.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { initZodDecorators } from '@wildo-ai/zod-decorators';\n\ninitZodDecorators(z);\n\n\n/**\n * One relationship, as it rides on BOTH resources it joins.\n *\n * ## Why an edge appears on two rows rather than on one\n *\n * A relationship genuinely IS a property of both resources — \"what is `deals` related to?\" is a\n * question about `deals` and about everything `deals` touches — so carrying it on both is a\n * statement of what it means, not an encoding chosen to fit a row shape. Hanging every edge off one\n * arbitrarily-chosen endpoint would be the encoding, and the choice would have to be re-derived by\n * every reader.\n *\n * The consumer draws each edge once, keyed by {@link relationshipId}. The duplication costs one extra\n * copy of a small object per edge and buys a row that is complete on its own.\n *\n * ## Why the vocabularies are plain strings\n *\n * These values cross a subprocess boundary from the OBSERVED application's registry, which may be\n * built against a different engine revision than the workbench. Binding `nature` or the cardinalities to the engine enums would make a\n * row the observed application can legitimately produce unparseable here — the workbench refusing to\n * show exactly the drift it exists to reveal.\n */\nexport const Workbench_DomainResourceRelationship_Schema = z.object({\n /**\n * Stable identity for ONE edge within this projection, composed from every field carried about it.\n *\n * NOT the `resourceType1__resourceType2__foreignKeyField` triple the retired\n * `workbenchResourceRelationships` resource addressed a row by: that triple is not total here,\n * because a MANY-to-MANY edge carries\n * `jointResourceType` and no `foreignKeyField`. Two edges agreeing on every field below are\n * indistinguishable to a graph, so merging them loses nothing a reader could have seen.\n */\n relationshipId: z.string().min(1),\n resourceType1: z.string().min(1),\n resourceType2: z.string().min(1),\n cardinality1: z.string().min(1),\n cardinality2: z.string().min(1),\n /**\n * `composition`, `reference` or `association` — every member `RelationshipNature` declares — kept as\n * a plain string for the drift-tolerance reason above, not because a fourth one exists today.\n */\n nature: z.string().min(1),\n /** The field carrying the join. Absent on a junction-backed MANY-to-MANY, which has no FK column. */\n foreignKeyField: z.string().min(1).nullable(),\n /**\n * Which side's rows CARRY the foreign key — the direction an arrow must point.\n *\n * Resolved by the framework's own `resolveForeignKeyHolderResourceType`, from CARDINALITY, never\n * from declaration order: `(TODOS, USERS, MANY, ONE, { foreignKeyField })` is a valid child-first\n * declaration that puts the referenced resource in `resourceType2`, so a consumer reading position\n * draws half its arrows backwards.\n */\n foreignKeyHolderResourceType: z.string().min(1),\n /** The junction resource of a MANY-to-MANY, which the framework requires such an edge to name. */\n jointResourceType: z.string().min(1).nullable(),\n /** Whether this edge is the structural ownership anchor giving `resourceType2` its scope. */\n isPrimaryScope: z.boolean(),\n /**\n * Whether the edge is DECLARED BUT INACTIVE.\n *\n * The one field here whose absence made the graph WRONG rather than thinner: a disabled edge\n * constrains nothing at runtime, so drawing it like a live one tells a reader the application has\n * a relationship it does not have. Carried even though the dogfood application disables none\n * (measured 2026-08-31: 0 of 16) — a field that is uniformly `false` today is exactly the one that\n * silently misleads the first time it is not.\n */\n isDisabled: z.boolean(),\n /**\n * How a caller reaches rows on the far side — `requires_context`, `standalone`, and whatever else\n * the observed application's engine revision declares.\n *\n * A plain string for the same drift-tolerance reason `nature` is one.\n */\n accessScopeStrategy: z.string().min(1).nullable(),\n /** Whether the parent endpoint is `mandatory` or `optional` for the child's addressing. */\n parentResourceRequirement: z.string().min(1).nullable(),\n /**\n * WHICH resource this edge anchors scope to, when it anchors one.\n *\n * Not derivable from {@link isPrimaryScope}, which says only THAT it anchors. On an edge whose\n * endpoints are both scoped, the two answer different questions.\n */\n primaryScope: z.string().min(1).nullable(),\n /** Whether a cycle through this edge is permitted — a graph-shape fact a graph should be able to show. */\n allowCycle: z.boolean(),\n});\n\nexport type Workbench_DomainResourceRelationship = z.infer<typeof Workbench_DomainResourceRelationship_Schema>;\n\n/**\n * ONE resource of the observed application's domain model — node, module membership, specification\n * and edges in a single row.\n *\n * ## Why every field is a summary field\n *\n * A LIST renders the SUMMARY projection, and this resource's list IS its whole purpose: the graph\n * consumes the collection. A field left out of the summary is a field the graph cannot draw, and the\n * omission is silent — the row arrives, the field is simply absent. So the summary here is the full\n * row by design rather than by neglect.\n *\n * ## Why this is one row per RESOURCE rather than one row per module or one row for the graph\n *\n * Edges are resource-to-resource. A module-per-node projection would have to AGGREGATE them, which\n * destroys precisely the meanings the framework refuses to merge — nature, cardinality, foreign-key\n * direction — and a graph that draws every edge as one grey line has lost information the flat table\n * at least preserved.\n */\nexport const Workbench_DomainResource_Schema = z.object({\n /**\n * Composed by the introspection source from the binding's `identityFields` (`['resourceType']`).\n *\n * `.isSummaryField()` on the IDENTITY field is load-bearing rather than cosmetic: the projection a\n * list renders is the summary, and a row with no id is a row nothing can address — the failure that\n * made every relationship row unclickable before its id was marked.\n */\n workbenchDomainResourceId: z.string().min(1).isPrimaryKey().isSummaryField(),\n resourceType: z.string().min(1).isSummaryField(),\n /**\n * The module that registers this resource, or `null`.\n *\n * `null` is a FACT, not a gap: no module of the observed application owns this resource, which is\n * true of every ENGINE resource — and an application merges all of them, since `initializeResources`\n * applies the engine's core factory map unconditionally and both registries merge it. They are\n * carried rather than dropped because they are part of the running application, and because an edge\n * to the resource that gives a row its tenant scope is the most load-bearing edge in the graph.\n *\n * No `origin` field restates this. The absence of a module IS the distinction, and a second field\n * saying the same thing is a second thing that can disagree with the first.\n */\n moduleId: z.string().min(1).isSummaryField().nullable(),\n /** `domain` or `engine` — the kind the owning module declares, when there is one. */\n moduleKind: z.string().min(1).isSummaryField().nullable(),\n /**\n * Which part of its owner this resource belongs to — a SECOND grouping axis, under the module.\n *\n * Sourced from `ResourceSpecificationConfig.subDomain`. For engine resources that is the closed\n * `EngineResourceSubDomain` vocabulary (`auth`, `billing`, `users`, …), which exists because the\n * engine's 85 resources otherwise arrive as one flat set and every surface that has to present them\n * invents a grouping of its own.\n *\n * A plain `string` here rather than that enum, and deliberately: this schema is shared by a\n * workbench that observes an application whose own sub-domains it cannot enumerate. Pinning the\n * engine's vocabulary here would make an application's value invalid at the wire.\n *\n * `null` means the resource specification declares none — an application resource today, or an engine\n * resource with no spec at all. A consumer grouping by this must carry an \"unclassified\" bucket and\n * say so, rather than folding those rows into a real group.\n */\n subDomain: z.string().min(1).isSummaryField().nullable(),\n /**\n * Every field of the materialized `mainSchema`, with everything the framework knows about it.\n *\n * This replaced a bare `fieldNames: string[]`, whose JSDoc argued that \"a domain-model panel\n * answers what a resource HOLDS\" and that per-field extraction \"belongs to `resource-specifications`\".\n * The premise was right and the conclusion aged badly: a NAME answers \"does this field exist\",\n * which the node already implies by counting them, and a reader who opens a resource wants what\n * the field IS. The cost was then MEASURED rather than assumed — 715 fields across the 82 engine\n * resources extract to 264 KB, a fraction of what the relationship edges already cost — so the\n * reason to withhold it was gone.\n *\n * `params`, `derived` and `origin` are OPAQUE records on purpose. They are the extractor's own\n * output — authored spec prose, framework-derived structure, base-vs-variant provenance — and each\n * is an open shape that grows with the decorators. Restating them field by field here would make\n * this schema a second, always-lagging copy of a contract `@wildo-ai/saas-specifications` owns;\n * a consumer that needs one reads it through that package's type.\n */\n fields: z.array(z.object({\n fieldName: z.string().min(1),\n /** Which `{primitive}Spec()` decorator carried the authored prose, when one did. */\n specDecorator: z.string().min(1).nullable(),\n params: z.record(z.string(), z.unknown()).nullable(),\n derived: z.record(z.string(), z.unknown()).nullable(),\n origin: z.record(z.string(), z.unknown()).nullable(),\n /**\n * The field's DECORATOR record, as the schema declares it — beside `derived`, which is the\n * extractor's interpretation of it.\n *\n * It carries what the interpretation drops: `isSummaryField`, `isHidden`, `excludeFromCreate` /\n * `excludeFromUpdate`, `dataCategories`, and the index / unique / primary-key trio.\n *\n * It does NOT carry `*.ui-behavior.tsx` configuration, and that is a reachability limit rather\n * than an omission: those decorators are applied by a FRONTEND module the companion never loads,\n * because the subprocess resolves `library`, `specifications` and `service` targets and there is\n * no frontend one. Measured on the engine's resources — zero UI keys present.\n */\n metadata: z.record(z.string(), z.unknown()).nullable(),\n })).isSummaryField(),\n /**\n * Every operation the resource declares, projected to what a READER needs.\n *\n * Never the DTOs. A materialized operation carries six Zod schemas — request, response, summary,\n * context, internal, repository — each serializing to tens of kilobytes, so carrying the operation\n * objects would put megabytes on the wire to say which verbs exist. What is here is the identity,\n * the variant, the authorization and the flags that change what the operation DOES.\n *\n * An EMPTY `roles` array is a real answer — no role gate on that variant — and not a gap.\n */\n operations: z.array(z.object({\n operationIdentifier: z.string().min(1),\n /** The TRANSPORT kind: `api_call`, `internal_call`, `repository_only`, … */\n variantType: z.string().min(1).nullable(),\n /**\n * WHICH variant of that transport — `admin`, `summary`, `context` — or `null` for the default.\n *\n * The missing half of an operation's IDENTITY, and its absence was a defect rather than missing\n * detail: `organizations` declares four operations that are all `read` × `api_call`, separated\n * only by this key, and across the engine's core map 133 of 794 operations collided on the pair\n * without it.\n */\n variantKey: z.string().min(1).nullable(),\n /** For a CUSTOM operation, the core verb it behaves like. `null` for a core operation. */\n resourceOperationLike: z.string().min(1).nullable(),\n isDefault: z.boolean(),\n roles: z.array(z.string()),\n riskLevel: z.string().min(1).nullable(),\n isUnimplemented: z.boolean(),\n isDisabled: z.boolean(),\n requiresStepUpAuthentication: z.boolean(),\n /**\n * The variant's `idempotencyKey` declaration (#535) — `accepted` or `required` — or null when it takes no key. A plain\n * string for the same reason as the other vocabularies here: the observed application may run another engine revision.\n */\n idempotencyKey: z.string().min(1).nullable(),\n /**\n * The action the variant's `submissionChallenge` declaration binds a caller's captcha token to (#1985), or null when a\n * caller who is not signed in answers no challenge. A plain string: an application names its own actions.\n */\n submissionChallengeAction: z.string().min(1).nullable(),\n admitsCrossTenantPlatformAdministration: z.boolean(),\n auditableEventType: z.string().min(1).nullable(),\n isMcpExposed: z.boolean(),\n requiredFeatures: z.array(z.string()),\n /**\n * Everything else the operation declares — HTTP verb, runtime mode, bulk and API-key posture,\n * notification fan-out, custom-implementation modes, authoritative fields.\n *\n * A DENY LIST over the operation's own keys on the producing side, for the same reason `advanced`\n * is, and this is the one that proved the argument: a hand-picked set of twelve fields shipped\n * without `variantKey`, `httpVerb`, `isBulkOperation` or `serviceRuntimeMode`. The six DTO\n * schemas are excluded by name — each serializes to tens of kilobytes.\n */\n attributes: z.record(z.string(), z.unknown()),\n /**\n * The authored specification for this operation, keyed by `operationIdentifier` — so every\n * VARIANT of one verb carries the same entry, which is what the specification describes.\n *\n * `null` means the specification does not mention the operation: a gap a reader can act on.\n */\n specification: z.record(z.string(), z.unknown()).nullable(),\n /** The authored `frontend.views` overlay for this operation, when there is one. */\n view: z.record(z.string(), z.unknown()).nullable(),\n })).isSummaryField(),\n /**\n * The operations for which the resource specification declares a FRONTEND view overlay (`frontend.views`).\n *\n * Refs only. The entries are authoring prose about how an operation surfaces, which belongs to a\n * specification reader; what a domain-model panel can act on is which operations have an authored\n * view and — by difference with `operations` — which do not.\n */\n viewRefs: z.array(z.string()).isSummaryField(),\n /**\n * The configuration facts that are neither prose nor structure — persistence, policy, bindings.\n *\n * Everything on the resource's `ResourceConfiguration` that decides how it BEHAVES rather than what\n * it holds: which database it lives in, whether it is a system resource, its retention,\n * transposition, portability and data-subject policies, its HTTP and introspection bindings.\n *\n * An OPAQUE record, and deliberately so. The producer builds it by DENY list over the\n * configuration's own keys rather than by enumerating the ones that exist today, because\n * `ResourceConfiguration` has grown several of these fields in as many months and an enumeration\n * reports the subset its author knew about. Typing it here would put that enumeration back.\n */\n advanced: z.record(z.string(), z.unknown()).isSummaryField(),\n /**\n * The authored specification's PROSE, or `null` when this resource has none.\n *\n * It rides in the row rather than being fetched on selection because a per-selection fetch is not\n * cheaper: `deriveRows` has no per-row path, so an addressed READ derives the WHOLE set and filters\n * it afterwards. \"Fetch the specification when a node is clicked\" would therefore be a second full\n * derivation of the entire application.\n */\n specification: z.object({\n /** Why this resource exists in the domain. */\n purpose: z.string(),\n /** The functional role it plays inside the business architecture. */\n businessRole: z.string(),\n /** How it evolves over time. Optional in the specification contract, so nullable here. */\n lifecycleRole: z.string().nullable(),\n /** Domain caveats not encoded structurally elsewhere. */\n businessConstraints: z.array(z.string()),\n }).isSummaryField().nullable(),\n /** Every relationship this resource participates in, on either side. */\n relationships: z.array(Workbench_DomainResourceRelationship_Schema).isSummaryField(),\n});\n\nexport type Workbench_DomainResource = z.infer<typeof Workbench_DomainResource_Schema>;\n\n/**\n * ONE FIELD of a domain resource — named so a consumer can hold one without re-deriving its type.\n *\n * Indexed off the row rather than declared separately, because the schema is the one authority for\n * the shape and a second declaration is a second thing that can drift from it.\n */\nexport type Workbench_DomainResourceField = Workbench_DomainResource['fields'][number];\n\n/** ONE OPERATION of a domain resource — indexed off the row, for the same reason. */\nexport type Workbench_DomainResourceOperation = Workbench_DomainResource['operations'][number];\n\n/**\n * The QUESTION a specification family answers — the axis the workbench groups them by.\n *\n * ## Why the families are grouped at all\n *\n * Fifteen rows in one undifferentiated list is a directory, not a review surface. A creator opening\n * the workbench is not looking for \"the `document-release-policy` family\"; they are looking for what\n * was decided about who this product is for, or about what it must promise. Grouping by the question\n * answered is what makes the list navigable without inventing twelve destinations.\n *\n * ## Why this is a display vocabulary and not a property of the family\n *\n * `ApplicationSpecificationFamilySemanticSchemaRef` names what a family MEANS and what validates it.\n * Nothing in the runtime branches on the concern below — it exists so a reader can find a row. Adding\n * it to the semantic authority would put a workbench presentation choice inside the contract the\n * journey lands artifacts against.\n *\n * The family → concern mapping deliberately lives with the projection that derives it (the\n * companion's `specification-artifacts` behavior), beside the semantic authority it must stay\n * exhaustive over, rather than here where the authority is not reachable.\n */\nexport enum WorkbenchSpecificationArtifactConcern {\n /** Why the product exists and who it is for — `vision-brief`, `market-snapshot`. */\n INTENT = 'intent',\n /** What it must do and what it costs — `requirements`, `feature-drafts`, `business-model`. */\n SCOPE = 'scope',\n /** How and when it gets built — `domain-plan`, `build-plan`, `roadmap`, `placement-plan`. */\n DELIVERY = 'delivery',\n /** How it presents itself — `brand-brief`. */\n IDENTITY = 'identity',\n /** What it must promise and publish — the assurance and governed-document families. */\n OBLIGATIONS = 'obligations',\n /**\n * A family the workbench has not been taught to group.\n *\n * A named member rather than a throw, and rather than silence. The population is derived from the\n * semantic authority, so a family added there arrives here with no classification — and the two\n * alternatives are both worse than a visible bucket: refusing the derivation would blank the whole\n * page over one unmapped row, and defaulting into a real concern would file the new family\n * somewhere plausible and wrong, which nobody would notice.\n *\n * A companion test asserts this member is currently UNUSED, so it stays a signal rather than\n * becoming a habit.\n */\n UNCLASSIFIED = 'unclassified',\n}\n\n/**\n * Whether a family has landed, and whether what landed still validates.\n *\n * THREE states, not two, because \"not landed\" and \"landed but invalid\" are the opposite instructions\n * to a reviewer: the first is work the journey has not done, the second is work it did that no longer\n * holds. A boolean `isValid` would report both as `false`.\n */\nexport enum WorkbenchSpecificationArtifactState {\n /** The family is exported by the application and its `_core` validator reports no error. */\n LANDED_VALID = 'landed_valid',\n /** The family is exported and its `_core` validator reports at least one ERROR-severity issue. */\n LANDED_INVALID = 'landed_invalid',\n /**\n * The application exports nothing for this family.\n *\n * Reported as a ROW rather than omitted — the same call `definition-specifications.behavior.ts`\n * makes for the same reason: *\"an omitted row and a family that does not exist would look the same\n * to the reader.\"* On a fresh application an empty list would say nothing; fifteen NOT_LANDED rows\n * say what the journey has left to produce.\n */\n NOT_LANDED = 'not_landed',\n}\n\n/**\n * One WARNING the family's validator reports on the landed content: where it sits in the artifact\n * (`path`, the validator's own dotted locator) and what it says (`message`, the validator's words).\n * A warning is authoring drift that does not invalidate the artifact — see `warnCount`.\n */\nexport const Workbench_SpecificationArtifactWarning_Schema = z.object({\n path: z.string(),\n message: z.string(),\n});\n\n/**\n * ONE application-specification family, projected for a human reviewer.\n *\n * ## Why the prose fields are markdown strings\n *\n * `StringDisplayMode.MARKDOWN` renders GFM through the framework's own display chrome, which is what\n * lets headings, lists and paragraphs survive into the page. The alternative — modelling each\n * family's shape as nested schema fields — would have to be done fifteen times, would freeze twelve\n * `_core` contracts into this projection, and would still render as a form rather than as a document.\n *\n * The rendering is an OUTLINE, never a table. That is the acceptance criterion this resource exists\n * to satisfy: these artifacts are prose-heavy and their value is in the rationale, so a projection\n * that put them in columns would destroy exactly what makes them worth reviewing.\n *\n * ## Why the heavy fields are NOT summary fields\n *\n * `document`, `issues`, `warnings`, `decisionRecord` and `diagram` are excluded from the summary by omission, so\n * a list carries the INDEX while a detail page carries the documents. One derivation still computes\n * all of them either way — this bounds the RESPONSE, not the work.\n *\n * Which variant a caller gets matters, and is easy to state wrongly: the LIST operation's DEFAULT\n * variant answers the full row, and it is the operation's `summary` variant that applies this\n * projection. Measured against the live wonder-crm companion, 2026-08-31:\n * `GET /api/v1/workbench-specification-artifacts` → **149,089 B**, and\n * `…/workbench-specification-artifacts/summary` → **3,654 B** carrying the eight fields marked\n * below. A list layout renders the summary variant — which is also why the addressing field must be\n * marked, or every row in that list is unclickable.\n */\nexport const Workbench_SpecificationArtifact_Schema = z.object({\n /**\n * The family id — `vision-brief`, `market-snapshot`, `compliance-program`.\n *\n * The source's own key, marked `.isSummaryField()` because a list row with no id is a row nothing\n * can address: the summary projection is what a click reads the target from.\n */\n family: z.string().min(1).isPrimaryKey().isSummaryField(),\n /** The family's name in a creator's words — `Vision`, `Market`, `Assurance programme`. */\n title: z.string().min(1).isSummaryField(),\n /**\n * What this family IS, in one sentence a creator recognizes — static per family, present whether\n * or not anything landed. This is the summary card's subtitle: a card reading only\n * \"Governed-document drafts · Not landed\" tells a reader nothing they can act on; \"The drafts of\n * the public documents this product must publish\" does.\n */\n description: z.string().min(1).isSummaryField(),\n /**\n * A one-line PULSE of the landed content — `\"3 ICPs · 5 personas · 2 positionings\"`, the vision's\n * own one-liner — or `null` when the family has not landed.\n *\n * Derived server-side from the RAW value so the list answers \"how much is in there\" without any\n * client downloading fifteen full documents. It is a COUNT-and-headline summary, never a\n * truncation of prose: a clipped sentence reads as an accident, a count reads as an answer.\n */\n contentSummary: z.string().nullable().isSummaryField(),\n /** The question this family answers, which is the axis the list groups by. */\n concern: z.enum(WorkbenchSpecificationArtifactConcern).systemEnum('WorkbenchSpecificationArtifactConcern').isSummaryField(),\n /** Landed and valid, landed and invalid, or not landed at all. */\n state: z.enum(WorkbenchSpecificationArtifactState).systemEnum('WorkbenchSpecificationArtifactState').isSummaryField(),\n /** The `_core` contract the family's content must satisfy, verbatim from the semantic authority. */\n schemaRef: z.string().min(1),\n /**\n * Where the family's file lives, relative to the application root — the file a reader opens when\n * the rendering is not enough.\n *\n * `null` when this runtime places no file for the family. A placement and a RENDER PROFILE are\n * different things (`playbook-output-landing-target`), and only the placement is asked for here.\n */\n sourcePath: z.string().min(1).nullable().isSummaryField(),\n /** ERROR-severity issues the family's own validator reports on the landed content, right now. */\n errorCount: z.number().int().nonnegative().isSummaryField(),\n /** WARN-severity issues — authoring drift that does not invalidate the artifact. */\n warnCount: z.number().int().nonnegative().isSummaryField(),\n /**\n * Every playbook whose declared `outputs[].family` is this family.\n *\n * This is the durable half of \"what produced it\": a fact about the compiled catalog, in git, true\n * whether or not any run's state survives. A link to the RUN that produced this particular value\n * was deliberately rejected — runs, traces and the write register are a per-run cache under\n * `one-source-of-truth.md` Rule 5, so a durable artifact pointing into deletable state is dangling\n * by design. The link runs the other way: a run may name what it wrote.\n *\n * Empty for a family no playbook produces — which is a finding, not a gap.\n */\n producedByPlaybookRefs: z.array(z.string()).isSummaryField(),\n /**\n * The landed family value, RAW — exactly the object the specifications package exports.\n *\n * ## Why the raw value rides beside its rendering\n *\n * The per-family presentations (workbench `artifact-presentation/`) render EDITORIALLY — an ICP\n * card, a requirement with its acceptance criteria, a placement decision with its rationale — and\n * an editorial arrangement needs the VALUE, not a markdown projection of it. The markdown\n * `document` below stays: it is the structural fallback every family keeps behind the content\n * error boundary, and the whole rendering for a family this build's vocabulary does not know.\n *\n * ## Untyped HERE, typed at the EDGE — a measured decision, not an omission\n *\n * The typed `_core` snapshot schemas live in `@wildo-ai/saas-specifications`, which depends on\n * `saas-frontend-lib` AND `saas-backend-lib` (its package.json) — while this package is the\n * platform's light contracts-only spine (`platform/CLAUDE.md`). Typing this field would drag the\n * whole engine into every consumer of this package for a shape only two consumers read. The two\n * readers type it themselves: the companion behavior validates through the semantic authority\n * before emitting, and the workbench templates narrow via TYPE-ONLY imports (erased at compile,\n * zero runtime dependency). Recorded with alternatives in\n * `.claude/plans/workbench-product-artifacts-ux-analysis.md` (D1).\n *\n * Deliberately NOT a summary field: the LIST carries the index, and this is the heaviest thing a\n * row owns. Emitted from the RAW landed value — never from a validator's parsed output, whose\n * schema `.default()`s would inject content the author never wrote.\n */\n content: z.record(z.string(), z.unknown()).nullable(),\n /**\n * The artifact rendered as a document, or `null` when the family has not landed.\n *\n * Produced by `renderSpecificationFamilyReviewDocument` — an outline over the landed value, not a\n * prompt block. The prompt renderers (`market-render-prompt`, `brand-render-prompt`) read the same\n * content for a language model and must never be reused here.\n */\n document: z.string().nullable(),\n /**\n * The validator's own findings, rendered for a reader, or `null` when there are none.\n *\n * Carried as content rather than as counts alone because a reviewer deciding whether to accept an\n * artifact needs to see WHICH rule failed and where, and the counts beside them in the list are\n * only the signal to come and look.\n */\n issues: z.string().nullable(),\n /**\n * Every WARNING the validator reports, structured, one entry per finding — `[]` when there are\n * none or the family has not landed. `warnCount` is its length.\n *\n * Structured rather than folded into `issues` (which carries the ERRORS) so the page names them in\n * its own authored words: until 2026-09-25 only the count left the companion, and the page could say\n * \"25 warnings\" and then had to send the reader to the file to learn what they were.\n */\n warnings: z.array(Workbench_SpecificationArtifactWarning_Schema),\n /**\n * `DECISIONS.md` committed beside the family, verbatim, or `null` when there is none.\n *\n * The strongest provenance this surface has: it names the playbook that produced the artifact and,\n * more importantly, records every question the creator was asked — including the ones they did NOT\n * answer, where \"the derivation chose for itself\". A run that asked nothing writes no such file, so\n * `null` here means \"no clarification was recorded\", never \"no clarification happened\".\n */\n decisionRecord: z.string().nullable(),\n /**\n * `DIAGRAM.md` committed beside the family, verbatim, or `null`.\n *\n * Three families have one today (`domain-plan`, `build-plan`, `roadmap`). It is surfaced rather\n * than re-derived: the diagram is already a committed output of the family, regenerated on every\n * landing, and rendering a second picture here would be a second thing that can disagree with it.\n */\n diagram: z.string().nullable(),\n});\n\nexport type Workbench_SpecificationArtifact = z.infer<typeof Workbench_SpecificationArtifact_Schema>;\n"]}
|