@protoyard/blueprint 0.0.0-stage → 1.1.0

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.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1149 -2
  3. package/dist/aggregate.d.ts +83 -0
  4. package/dist/aggregate.js +268 -0
  5. package/dist/app-model.d.ts +76 -0
  6. package/dist/app-model.js +287 -0
  7. package/dist/archetypes/index.d.ts +1 -0
  8. package/dist/archetypes/index.js +1 -0
  9. package/dist/archetypes/schema.d.ts +126 -0
  10. package/dist/archetypes/schema.js +77 -0
  11. package/dist/audit.d.ts +52 -0
  12. package/dist/audit.js +149 -0
  13. package/dist/authoring/deck-lint.d.ts +32 -0
  14. package/dist/authoring/deck-lint.js +567 -0
  15. package/dist/authoring/index.d.ts +1 -0
  16. package/dist/authoring/index.js +1 -0
  17. package/dist/authoring/select-deck-layouts.d.ts +50 -0
  18. package/dist/authoring/select-deck-layouts.js +213 -0
  19. package/dist/authoring-apis.d.ts +13 -0
  20. package/dist/authoring-apis.js +13 -0
  21. package/dist/authoring-validation.d.ts +65 -0
  22. package/dist/authoring-validation.js +267 -0
  23. package/dist/avatar.d.ts +25 -0
  24. package/dist/avatar.js +30 -0
  25. package/dist/brand.d.ts +70 -0
  26. package/dist/brand.js +294 -0
  27. package/dist/brief/archetypes.d.ts +28 -0
  28. package/dist/brief/archetypes.js +798 -0
  29. package/dist/brief/content-synthesize.d.ts +31 -0
  30. package/dist/brief/content-synthesize.js +210 -0
  31. package/dist/brief/deck-outlines.d.ts +96 -0
  32. package/dist/brief/deck-outlines.js +561 -0
  33. package/dist/brief/draft-bodies.d.ts +29 -0
  34. package/dist/brief/draft-bodies.js +224 -0
  35. package/dist/brief/fields.d.ts +19 -0
  36. package/dist/brief/fields.js +229 -0
  37. package/dist/brief/index.d.ts +8 -0
  38. package/dist/brief/index.js +8 -0
  39. package/dist/brief/kind-detection.d.ts +69 -0
  40. package/dist/brief/kind-detection.js +353 -0
  41. package/dist/brief/limits.d.ts +117 -0
  42. package/dist/brief/limits.js +217 -0
  43. package/dist/brief/page-doc-outlines.d.ts +80 -0
  44. package/dist/brief/page-doc-outlines.js +485 -0
  45. package/dist/brief/synthesize.d.ts +59 -0
  46. package/dist/brief/synthesize.js +511 -0
  47. package/dist/brief/text.d.ts +13 -0
  48. package/dist/brief/text.js +59 -0
  49. package/dist/canvas-screen.d.ts +31 -0
  50. package/dist/canvas-screen.js +33 -0
  51. package/dist/canvas-seed.d.ts +58 -0
  52. package/dist/canvas-seed.js +82 -0
  53. package/dist/computed/evaluate.d.ts +11 -0
  54. package/dist/computed/evaluate.js +101 -0
  55. package/dist/computed/index.d.ts +4 -0
  56. package/dist/computed/index.js +3 -0
  57. package/dist/computed/public.d.ts +14 -0
  58. package/dist/computed/public.js +19 -0
  59. package/dist/computed/schema.d.ts +10 -0
  60. package/dist/computed/schema.js +140 -0
  61. package/dist/computed/types.d.ts +70 -0
  62. package/dist/computed/types.js +1 -0
  63. package/dist/computed/validate.d.ts +6 -0
  64. package/dist/computed/validate.js +146 -0
  65. package/dist/csv-guard.d.ts +15 -0
  66. package/dist/csv-guard.js +29 -0
  67. package/dist/csv.d.ts +85 -0
  68. package/dist/csv.js +288 -0
  69. package/dist/files.d.ts +35 -0
  70. package/dist/files.js +246 -0
  71. package/dist/form-schema.d.ts +124 -0
  72. package/dist/form-schema.js +300 -0
  73. package/dist/generator-version.d.ts +11 -0
  74. package/dist/generator-version.js +51 -0
  75. package/dist/generator.d.ts +34 -0
  76. package/dist/generator.js +445 -0
  77. package/dist/identity.d.ts +34 -0
  78. package/dist/identity.js +91 -0
  79. package/dist/import/csv-shape.d.ts +40 -0
  80. package/dist/import/csv-shape.js +265 -0
  81. package/dist/import/json-shape.d.ts +55 -0
  82. package/dist/import/json-shape.js +491 -0
  83. package/dist/import/limits.d.ts +13 -0
  84. package/dist/import/limits.js +14 -0
  85. package/dist/import/sqlite-schema.d.ts +36 -0
  86. package/dist/import/sqlite-schema.js +729 -0
  87. package/dist/index.d.ts +60 -0
  88. package/dist/index.js +58 -0
  89. package/dist/kinds/anchors.d.ts +18 -0
  90. package/dist/kinds/anchors.js +46 -0
  91. package/dist/kinds/bodies.d.ts +6 -0
  92. package/dist/kinds/bodies.js +32 -0
  93. package/dist/kinds/brand-runtime.d.ts +19 -0
  94. package/dist/kinds/brand-runtime.js +35 -0
  95. package/dist/kinds/deck.d.ts +8 -0
  96. package/dist/kinds/deck.js +34 -0
  97. package/dist/kinds/doc.d.ts +19 -0
  98. package/dist/kinds/doc.js +41 -0
  99. package/dist/kinds/embed/index.d.ts +39 -0
  100. package/dist/kinds/embed/index.js +91 -0
  101. package/dist/kinds/envelope.d.ts +159 -0
  102. package/dist/kinds/envelope.js +78 -0
  103. package/dist/kinds/index.d.ts +11 -0
  104. package/dist/kinds/index.js +11 -0
  105. package/dist/kinds/kind.d.ts +36 -0
  106. package/dist/kinds/kind.js +55 -0
  107. package/dist/kinds/limits.d.ts +64 -0
  108. package/dist/kinds/limits.js +190 -0
  109. package/dist/kinds/page-doc-runtime.d.ts +37 -0
  110. package/dist/kinds/page-doc-runtime.js +55 -0
  111. package/dist/kinds/page.d.ts +16 -0
  112. package/dist/kinds/page.js +67 -0
  113. package/dist/kinds/parse.d.ts +18 -0
  114. package/dist/kinds/parse.js +27 -0
  115. package/dist/kinds/runtime.d.ts +128 -0
  116. package/dist/kinds/runtime.js +206 -0
  117. package/dist/kinds/services.d.ts +49 -0
  118. package/dist/kinds/services.js +249 -0
  119. package/dist/kinds/testing.d.ts +9 -0
  120. package/dist/kinds/testing.js +16 -0
  121. package/dist/migrations.d.ts +97 -0
  122. package/dist/migrations.js +351 -0
  123. package/dist/motion.d.ts +50 -0
  124. package/dist/motion.js +52 -0
  125. package/dist/notifications.d.ts +19 -0
  126. package/dist/notifications.js +177 -0
  127. package/dist/patch.d.ts +122 -0
  128. package/dist/patch.js +322 -0
  129. package/dist/policy.d.ts +23 -0
  130. package/dist/policy.js +105 -0
  131. package/dist/runtime-definition.d.ts +39 -0
  132. package/dist/runtime-definition.js +74 -0
  133. package/dist/scenarios.d.ts +9 -0
  134. package/dist/scenarios.js +49 -0
  135. package/dist/schema/blueprint.schema.json +10191 -0
  136. package/dist/schema-json.d.ts +6 -0
  137. package/dist/schema-json.js +36 -0
  138. package/dist/schema.d.ts +6348 -0
  139. package/dist/schema.js +1269 -0
  140. package/dist/search.d.ts +16 -0
  141. package/dist/search.js +96 -0
  142. package/dist/services.d.ts +89 -0
  143. package/dist/services.js +898 -0
  144. package/dist/share.d.ts +78 -0
  145. package/dist/share.js +234 -0
  146. package/dist/sheet-screen.d.ts +49 -0
  147. package/dist/sheet-screen.js +91 -0
  148. package/dist/storage.d.ts +43 -0
  149. package/dist/storage.js +179 -0
  150. package/dist/stream.d.ts +26 -0
  151. package/dist/stream.js +173 -0
  152. package/dist/untrusted.d.ts +63 -0
  153. package/dist/untrusted.js +502 -0
  154. package/dist/validation-tasks.d.ts +178 -0
  155. package/dist/validation-tasks.js +199 -0
  156. package/dist/validation.d.ts +35 -0
  157. package/dist/validation.js +312 -0
  158. package/dist/variants.d.ts +112 -0
  159. package/dist/variants.js +283 -0
  160. package/dist/workflows/index.d.ts +3 -0
  161. package/dist/workflows/index.js +3 -0
  162. package/dist/workflows/schema.d.ts +50 -0
  163. package/dist/workflows/schema.js +34 -0
  164. package/dist/workflows/transition.d.ts +15 -0
  165. package/dist/workflows/transition.js +25 -0
  166. package/dist/workflows/validate.d.ts +17 -0
  167. package/dist/workflows/validate.js +140 -0
  168. package/package.json +120 -3
package/dist/audit.js ADDED
@@ -0,0 +1,149 @@
1
+ import { createRuntimeId } from '@protoyard/core';
2
+ import { FEATURE_TABLES } from "./storage.js";
3
+ import { inputProperty } from "./validation.js";
4
+ /** Placeholder stored instead of a sensitive field's real value. */
5
+ export const AUDIT_REDACTED = '[redacted]';
6
+ const META = new Set(['id', 'createdAt', 'updatedAt', 'deletedAt', 'deletedBy']);
7
+ function same(a, b) {
8
+ if (Object.is(a, b))
9
+ return true;
10
+ if (a === null || a === undefined || b === null || b === undefined)
11
+ return a === b;
12
+ if (Array.isArray(a) && Array.isArray(b)) {
13
+ if (a.length !== b.length)
14
+ return false;
15
+ return a.every((item, i) => same(item, b[i]));
16
+ }
17
+ if (typeof a === 'object' && typeof b === 'object') {
18
+ try {
19
+ return JSON.stringify(a) === JSON.stringify(b);
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+ function redact(field, value) {
28
+ if (value === undefined)
29
+ return null;
30
+ if (field?.sensitive)
31
+ return AUDIT_REDACTED;
32
+ return value;
33
+ }
34
+ /**
35
+ * Field-level diff for an audit row. Only changed input properties are listed;
36
+ * `sensitive` fields store {@link AUDIT_REDACTED} instead of the real value.
37
+ * Platform meta columns (`id`, timestamps, soft-delete markers) are omitted.
38
+ */
39
+ export function auditDiff(entity, before, after) {
40
+ const byProp = new Map(entity.fields.map((field) => [inputProperty(field), field]));
41
+ const keys = new Set([...byProp.keys()]);
42
+ if (before)
43
+ for (const key of Object.keys(before))
44
+ if (!META.has(key))
45
+ keys.add(key);
46
+ if (after)
47
+ for (const key of Object.keys(after))
48
+ if (!META.has(key))
49
+ keys.add(key);
50
+ const changes = {};
51
+ for (const key of [...keys].sort()) {
52
+ if (META.has(key))
53
+ continue;
54
+ const field = byProp.get(key);
55
+ const prev = before ? before[key] : undefined;
56
+ const next = after ? after[key] : undefined;
57
+ if (same(prev, next))
58
+ continue;
59
+ // Create: skip pure empties on the "before" side only when both empty.
60
+ if (before == null && (next === null || next === undefined))
61
+ continue;
62
+ changes[key] = {
63
+ before: before == null ? null : redact(field, prev),
64
+ after: after == null ? null : redact(field, next),
65
+ };
66
+ }
67
+ return changes;
68
+ }
69
+ /**
70
+ * Writes audit rows into the caller's open mutation transaction.
71
+ * No-op when the entity does not enable `features.audit`.
72
+ */
73
+ export function createAuditWriter(runtime, blueprint) {
74
+ const db = runtime.db;
75
+ const enabled = new Set(blueprint.entities.filter((entity) => entity.features.audit).map((entity) => entity.name));
76
+ let seq = 0;
77
+ return async (event) => {
78
+ if (!enabled.has(event.entity.name))
79
+ return null;
80
+ const actorId = runtime.session.principal()?.persona.id;
81
+ if (!actorId)
82
+ throw new Error('No active persona. Load a scenario first.');
83
+ const changes = auditDiff(event.entity, event.before, event.after);
84
+ // Always record the action even when the diff is empty (e.g. no-op update
85
+ // is rare; delete/create still carry structural meaning).
86
+ const entry = {
87
+ id: createRuntimeId('audit'),
88
+ entity: event.entity.name,
89
+ recordId: event.recordId,
90
+ actorId,
91
+ action: event.action,
92
+ at: runtime.clock.now().toISOString(),
93
+ seq: ++seq,
94
+ changes,
95
+ };
96
+ await db.table(FEATURE_TABLES.audit).put(entry);
97
+ return entry;
98
+ };
99
+ }
100
+ /** Read API for the shared `auditEntries` table. */
101
+ export function createAuditService(runtime, blueprint) {
102
+ const db = runtime.db;
103
+ const byName = new Map(blueprint.entities.map((entity) => [entity.name, entity]));
104
+ const audited = blueprint.entities.filter((entity) => entity.features.audit);
105
+ const assertCanRead = (entityName) => {
106
+ const entity = byName.get(entityName);
107
+ if (!entity?.features.audit) {
108
+ throw new Error(`Entity "${entityName}" does not enable audit logging.`);
109
+ }
110
+ runtime.session.assert(`${entity.name}:read`);
111
+ };
112
+ const sortNewest = (rows) => rows.sort((a, b) => {
113
+ if (a.at !== b.at)
114
+ return a.at < b.at ? 1 : -1;
115
+ const seqA = typeof a.seq === 'number' ? a.seq : 0;
116
+ const seqB = typeof b.seq === 'number' ? b.seq : 0;
117
+ if (seqA !== seqB)
118
+ return seqB - seqA;
119
+ return a.id < b.id ? 1 : a.id > b.id ? -1 : 0;
120
+ });
121
+ return {
122
+ async listForRecord(entityName, recordId) {
123
+ assertCanRead(entityName);
124
+ const rows = (await db.table(FEATURE_TABLES.audit).toArray());
125
+ return sortNewest(rows.filter((row) => row.entity === entityName && row.recordId === recordId));
126
+ },
127
+ async listRecent(limit = 50) {
128
+ if (audited.length === 0)
129
+ return [];
130
+ // Any audited entity the actor can read unlocks the feed.
131
+ const allowed = new Set();
132
+ for (const entity of audited) {
133
+ if (runtime.session.can(`${entity.name}:read`))
134
+ allowed.add(entity.name);
135
+ }
136
+ if (allowed.size === 0) {
137
+ const first = audited[0];
138
+ if (first)
139
+ runtime.session.assert(`${first.name}:read`);
140
+ }
141
+ const rows = (await db.table(FEATURE_TABLES.audit).toArray());
142
+ return sortNewest(rows.filter((row) => allowed.has(row.entity))).slice(0, Math.max(0, limit));
143
+ },
144
+ };
145
+ }
146
+ /** True when at least one entity opts into audit logging. */
147
+ export function blueprintUsesAudit(blueprint) {
148
+ return blueprint.entities.some((entity) => entity.features.audit);
149
+ }
@@ -0,0 +1,32 @@
1
+ export type DeckLintSeverity = 'error' | 'warning';
2
+ /** Stable structural diagnostic returned by the deck authoring lint. */
3
+ export type DeckLintDiagnostic = {
4
+ code: string;
5
+ severity: DeckLintSeverity;
6
+ path: (string | number)[];
7
+ jsonPath: string;
8
+ message: string;
9
+ };
10
+ /** Pure result suitable for CLI output and editor integrations. */
11
+ export type DeckLintResult = {
12
+ valid: boolean;
13
+ diagnostics: DeckLintDiagnostic[];
14
+ };
15
+ /**
16
+ * Check the structure and navigation references in an untrusted deck body.
17
+ * This function is deterministic, does not mutate input, render content or
18
+ * access the network. Diagnostics use paths relative to the deck object.
19
+ */
20
+ export declare function lintDeckStructure(input: unknown): DeckLintResult;
21
+ /**
22
+ * Check accessible content and static readability guidance for an untrusted
23
+ * deck. Schema omissions are errors; word-count estimates and missing speaker
24
+ * notes are warnings. Rendered contrast, font size and fit still need visual QA.
25
+ */
26
+ export declare function lintDeckContent(input: unknown): DeckLintResult;
27
+ /**
28
+ * Inspect media references in raw deck JSON without fetching, parsing remote
29
+ * content, or invoking object accessors. HTTPS is syntax-checked only; runtime
30
+ * hosts apply their own media policy. Embedded-app data is walked recursively.
31
+ */
32
+ export declare function lintDeckAssets(input: unknown): DeckLintResult;