@happyvertical/smrt-fields 0.40.60 → 0.40.62

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 (218) hide show
  1. package/AGENTS.md +58 -12
  2. package/README.md +143 -42
  3. package/dist/__smrt-register__.d.ts +2 -0
  4. package/dist/__smrt-register__.d.ts.map +1 -0
  5. package/dist/cache.d.ts +18 -0
  6. package/dist/cache.d.ts.map +1 -0
  7. package/dist/chunks/FieldPolicyCollection--RxukfCX.js +1218 -0
  8. package/dist/chunks/FieldPolicyCollection--RxukfCX.js.map +1 -0
  9. package/dist/collections/FieldPolicyCollection.d.ts +95 -0
  10. package/dist/collections/FieldPolicyCollection.d.ts.map +1 -0
  11. package/dist/collections/FieldPolicySuggestionCollection.d.ts +160 -0
  12. package/dist/collections/FieldPolicySuggestionCollection.d.ts.map +1 -0
  13. package/dist/collections/FieldUsageCounterCollection.d.ts +143 -0
  14. package/dist/collections/FieldUsageCounterCollection.d.ts.map +1 -0
  15. package/dist/deterministic-id.d.ts +18 -0
  16. package/dist/deterministic-id.d.ts.map +1 -0
  17. package/dist/field-definitions.d.ts +85 -0
  18. package/dist/field-definitions.d.ts.map +1 -0
  19. package/dist/field-policy-resolver.d.ts +46 -0
  20. package/dist/field-policy-resolver.d.ts.map +1 -0
  21. package/dist/index.d.ts +15 -532
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +1813 -628
  24. package/dist/index.js.map +1 -1
  25. package/dist/manifest.json +1487 -191
  26. package/dist/models/FieldPolicy.d.ts +163 -0
  27. package/dist/models/FieldPolicy.d.ts.map +1 -0
  28. package/dist/models/FieldPolicySuggestion.d.ts +132 -0
  29. package/dist/models/FieldPolicySuggestion.d.ts.map +1 -0
  30. package/dist/models/FieldUsageCounter.d.ts +178 -0
  31. package/dist/models/FieldUsageCounter.d.ts.map +1 -0
  32. package/dist/models/FieldUsageReportReceipt.d.ts +25 -0
  33. package/dist/models/FieldUsageReportReceipt.d.ts.map +1 -0
  34. package/dist/permissions.d.ts +9 -0
  35. package/dist/permissions.d.ts.map +1 -0
  36. package/dist/playground.d.ts +2 -0
  37. package/dist/playground.d.ts.map +1 -0
  38. package/dist/playground.js +39 -0
  39. package/dist/playground.js.map +1 -0
  40. package/dist/settings-catalog.d.ts +73 -0
  41. package/dist/settings-catalog.d.ts.map +1 -0
  42. package/dist/smrt-knowledge.json +449 -9
  43. package/dist/svelte/__tests__/FieldPolicyControlPanel.test.js +277 -0
  44. package/dist/svelte/__tests__/FieldPolicyGear.test.js +503 -0
  45. package/dist/svelte/__tests__/FormHelp.test.js +138 -0
  46. package/dist/svelte/__tests__/ModeUX.test.js +109 -0
  47. package/dist/svelte/__tests__/ObjectForm.test.js +687 -0
  48. package/dist/svelte/__tests__/ObjectFormGeneratedApi.integration.test.js +436 -0
  49. package/dist/svelte/__tests__/PolicyField.test.js +373 -0
  50. package/dist/svelte/__tests__/UsageLearning.test.js +140 -0
  51. package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte +30 -0
  52. package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts +9 -0
  53. package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts.map +1 -0
  54. package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte +33 -0
  55. package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts +10 -0
  56. package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts.map +1 -0
  57. package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte +19 -0
  58. package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts +10 -0
  59. package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts.map +1 -0
  60. package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte +18 -0
  61. package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts +11 -0
  62. package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts.map +1 -0
  63. package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte +11 -0
  64. package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts +19 -0
  65. package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts.map +1 -0
  66. package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte +18 -0
  67. package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts +8 -0
  68. package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts.map +1 -0
  69. package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte +24 -0
  70. package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts +13 -0
  71. package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts.map +1 -0
  72. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte +37 -0
  73. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts +15 -0
  74. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts.map +1 -0
  75. package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte +17 -0
  76. package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts +10 -0
  77. package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts.map +1 -0
  78. package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte +25 -0
  79. package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts +10 -0
  80. package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts.map +1 -0
  81. package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte +34 -0
  82. package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts +10 -0
  83. package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts.map +1 -0
  84. package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte +29 -0
  85. package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts +11 -0
  86. package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts.map +1 -0
  87. package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte +33 -0
  88. package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts +9 -0
  89. package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts.map +1 -0
  90. package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte +40 -0
  91. package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts +8 -0
  92. package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts.map +1 -0
  93. package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte +26 -0
  94. package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts +13 -0
  95. package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts.map +1 -0
  96. package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte +39 -0
  97. package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts +17 -0
  98. package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts.map +1 -0
  99. package/dist/svelte/__tests__/fixtures/RegistryInput.svelte +15 -0
  100. package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts +5 -0
  101. package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts.map +1 -0
  102. package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte +29 -0
  103. package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts +14 -0
  104. package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts.map +1 -0
  105. package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte +24 -0
  106. package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts +14 -0
  107. package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts.map +1 -0
  108. package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte +28 -0
  109. package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts +13 -0
  110. package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts.map +1 -0
  111. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte +23 -0
  112. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts +10 -0
  113. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts.map +1 -0
  114. package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte +14 -0
  115. package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts +19 -0
  116. package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts.map +1 -0
  117. package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte +25 -0
  118. package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts +14 -0
  119. package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts.map +1 -0
  120. package/dist/svelte/__tests__/settings-catalog.test.js +161 -0
  121. package/dist/svelte/components/AdvancedFields.svelte +49 -0
  122. package/dist/svelte/components/AdvancedFields.svelte.d.ts +17 -0
  123. package/dist/svelte/components/AdvancedFields.svelte.d.ts.map +1 -0
  124. package/dist/svelte/components/FieldInput.svelte +159 -0
  125. package/dist/svelte/components/FieldInput.svelte.d.ts +5 -0
  126. package/dist/svelte/components/FieldInput.svelte.d.ts.map +1 -0
  127. package/dist/svelte/components/FieldPolicyControlPanel.svelte +288 -0
  128. package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts +29 -0
  129. package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts.map +1 -0
  130. package/dist/svelte/components/FieldPolicyEditor.svelte +417 -0
  131. package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts +18 -0
  132. package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts.map +1 -0
  133. package/dist/svelte/components/FieldPolicyGearButton.svelte +24 -0
  134. package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts +8 -0
  135. package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts.map +1 -0
  136. package/dist/svelte/components/FieldPolicyGearProvider.svelte +169 -0
  137. package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts +20 -0
  138. package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts.map +1 -0
  139. package/dist/svelte/components/FieldPolicyProvider.svelte +89 -0
  140. package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts +35 -0
  141. package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts.map +1 -0
  142. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte +135 -0
  143. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts +11 -0
  144. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts.map +1 -0
  145. package/dist/svelte/components/FormHelp.svelte +157 -0
  146. package/dist/svelte/components/FormHelp.svelte.d.ts +15 -0
  147. package/dist/svelte/components/FormHelp.svelte.d.ts.map +1 -0
  148. package/dist/svelte/components/ModeSwitch.svelte +47 -0
  149. package/dist/svelte/components/ModeSwitch.svelte.d.ts +10 -0
  150. package/dist/svelte/components/ModeSwitch.svelte.d.ts.map +1 -0
  151. package/dist/svelte/components/ObjectForm.svelte +440 -0
  152. package/dist/svelte/components/ObjectForm.svelte.d.ts +50 -0
  153. package/dist/svelte/components/ObjectForm.svelte.d.ts.map +1 -0
  154. package/dist/svelte/components/ObjectFormSourceProvider.svelte +18 -0
  155. package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts +11 -0
  156. package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts.map +1 -0
  157. package/dist/svelte/components/PolicyField.svelte +338 -0
  158. package/dist/svelte/components/PolicyField.svelte.d.ts +80 -0
  159. package/dist/svelte/components/PolicyField.svelte.d.ts.map +1 -0
  160. package/dist/svelte/context.svelte.d.ts +54 -0
  161. package/dist/svelte/context.svelte.d.ts.map +1 -0
  162. package/dist/svelte/context.svelte.js +55 -0
  163. package/dist/svelte/data-table.d.ts +17 -0
  164. package/dist/svelte/data-table.d.ts.map +1 -0
  165. package/dist/svelte/data-table.js +19 -0
  166. package/dist/svelte/field-policy-editor.d.ts +81 -0
  167. package/dist/svelte/field-policy-editor.d.ts.map +1 -0
  168. package/dist/svelte/field-policy-editor.js +120 -0
  169. package/dist/svelte/gear-context.svelte.d.ts +16 -0
  170. package/dist/svelte/gear-context.svelte.d.ts.map +1 -0
  171. package/dist/svelte/gear-context.svelte.js +15 -0
  172. package/dist/svelte/index.d.ts +63 -0
  173. package/dist/svelte/index.d.ts.map +1 -0
  174. package/dist/svelte/index.js +41 -0
  175. package/dist/svelte/input-registry.d.ts +21 -0
  176. package/dist/svelte/input-registry.d.ts.map +1 -0
  177. package/dist/svelte/input-registry.js +26 -0
  178. package/dist/svelte/object-form-source-context.svelte.d.ts +4 -0
  179. package/dist/svelte/object-form-source-context.svelte.d.ts.map +1 -0
  180. package/dist/svelte/object-form-source-context.svelte.js +8 -0
  181. package/dist/svelte/object-form-source.svelte.d.ts +18 -0
  182. package/dist/svelte/object-form-source.svelte.d.ts.map +1 -0
  183. package/dist/svelte/object-form-source.svelte.js +99 -0
  184. package/dist/svelte/object-form.d.ts +6 -0
  185. package/dist/svelte/object-form.d.ts.map +1 -0
  186. package/dist/svelte/object-form.js +38 -0
  187. package/dist/svelte/playground/FieldPolicyFormPreview.svelte +212 -0
  188. package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts +4 -0
  189. package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts.map +1 -0
  190. package/dist/svelte/playground/ObjectFormPreview.svelte +129 -0
  191. package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts +4 -0
  192. package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts.map +1 -0
  193. package/dist/svelte/playground.d.ts +20 -0
  194. package/dist/svelte/playground.d.ts.map +1 -0
  195. package/dist/svelte/playground.js +38 -0
  196. package/dist/svelte/settings-catalog.d.ts +54 -0
  197. package/dist/svelte/settings-catalog.d.ts.map +1 -0
  198. package/dist/svelte/settings-catalog.js +116 -0
  199. package/dist/svelte/suggestions.d.ts +38 -0
  200. package/dist/svelte/suggestions.d.ts.map +1 -0
  201. package/dist/svelte/suggestions.js +68 -0
  202. package/dist/svelte/types.d.ts +101 -0
  203. package/dist/svelte/types.d.ts.map +1 -0
  204. package/dist/svelte/types.js +4 -0
  205. package/dist/svelte/usage-capture.d.ts +63 -0
  206. package/dist/svelte/usage-capture.d.ts.map +1 -0
  207. package/dist/svelte/usage-capture.js +61 -0
  208. package/dist/types.d.ts +316 -203
  209. package/dist/types.d.ts.map +1 -0
  210. package/dist/types.js +7 -1
  211. package/dist/types.js.map +1 -1
  212. package/dist/usage-learning.d.ts +201 -0
  213. package/dist/usage-learning.d.ts.map +1 -0
  214. package/dist/usage-schedules.d.ts +110 -0
  215. package/dist/usage-schedules.d.ts.map +1 -0
  216. package/dist/users-module.d.ts +30 -0
  217. package/dist/users-module.d.ts.map +1 -0
  218. package/package.json +33 -8
@@ -0,0 +1,143 @@
1
+ import { SmrtCollection } from '@happyvertical/smrt-core';
2
+ import { RegisteredFieldInfo } from '../field-definitions.js';
3
+ import { FieldUsageCounter } from '../models/FieldUsageCounter.js';
4
+ import { FieldUsageReportEntry, FieldUsageReportResult } from '../types.js';
5
+ /**
6
+ * Deviation comparison: strict equality, then a JSON round-trip so structured
7
+ * and Date-shaped values compare by serialization. Mirrors the browser-side
8
+ * `fieldUsageValuesEqual` (the packaging boundary bars value imports across the
9
+ * subpath split — the permission-slug precedent); a node test pins the two
10
+ * behaviours equal.
11
+ */
12
+ export declare function usageValuesEqual(a: unknown, b: unknown): boolean;
13
+ /**
14
+ * Per-call bound on reported entries — the rate rail for the fire-and-forget
15
+ * ingestion action (the resolveBatch precedent). The browser deliberately
16
+ * does not impose a duplicate limit: every report is server-bounded here.
17
+ */
18
+ export declare const MAX_USAGE_REPORT_ENTRIES = 100;
19
+ /**
20
+ * Collection surface for {@link FieldUsageCounter} plus the batched usage
21
+ * ingestion action (#2051).
22
+ *
23
+ * `reportUsage` is a custom collection-scoped action (the resolveBatch
24
+ * mechanism — single-segment path, so the generated SvelteKit transport AND
25
+ * core's runtime `APIGenerator` both dispatch it). Everything else is CLOSED:
26
+ * no generated CRUD, no CLI, no MCP — counters are written only through this
27
+ * action and read only by trusted server-side code (the learning jobs).
28
+ */
29
+ export declare class FieldUsageCounterCollection extends SmrtCollection<FieldUsageCounter> {
30
+ static readonly _itemClass: typeof FieldUsageCounter;
31
+ /**
32
+ * Record a batch of field submissions into the current UTC-day counters.
33
+ *
34
+ * Identity is AMBIENT-ONLY (the resolveBatch posture): the tenant AND the
35
+ * user come exclusively from the tenant context established by the app's
36
+ * auth hook — the request body cannot attribute usage to another tenant or
37
+ * user. Both are REQUIRED and the call fails closed without them (#2047
38
+ * round-3 posture):
39
+ *
40
+ * - No ambient tenant ⇒ the report is unattributable.
41
+ * - No ambient USER ⇒ the caller is an unauthenticated principal (a
42
+ * deployment that resolves the tenant from host/header alone). Such
43
+ * callers could otherwise inflate counts and histograms without bound
44
+ * (the batch cap is per call), and `distinctUsers` — the promote signal —
45
+ * is meaningless without a principal. Consequence, accepted deliberately:
46
+ * ANONYMOUS/PUBLIC FORMS DO NOT CONTRIBUTE USAGE. The learning loop is
47
+ * for authenticated org users.
48
+ *
49
+ * Any authenticated in-tenant principal may report (no manage slug needed).
50
+ * A durable receipt admits at most one `(tenant, user, object, field, UTC
51
+ * day)` contribution, and the batch stays bounded per call
52
+ * ({@link MAX_USAGE_REPORT_ENTRIES}).
53
+ *
54
+ * Server-side derivation (the client is never the authority):
55
+ * - Fields are validated against the live `ObjectRegistry`; unknown or
56
+ * non-usage-addressable entries (system, relationship pseudo-fields, STI
57
+ * meta storage, transient) are DROPPED and counted, never failing the
58
+ * batch (stale clients after a redeploy are expected).
59
+ * - Sensitivity comes from BOTH `field.sensitive` and `field._meta.sensitive`
60
+ * (and `readPermission` in both places): such fields are recorded
61
+ * COUNT-ONLY — their values are never persisted anywhere in usage data,
62
+ * default-matching or not.
63
+ * - DEVIATION (`setCount`, distinct users) is decided by comparing the
64
+ * submitted value against the default RESOLVED HERE for the calling
65
+ * identity — never against a client claim. Every accepted entry also
66
+ * increments `submissionCount`, the dominance denominator.
67
+ * - Values are histogrammed only for low-cardinality field types
68
+ * (`boolean`, `foreignKey`, `crossPackageRef`) with type-checked samples;
69
+ * free text is never histogrammed.
70
+ *
71
+ * Bounded trust in `matchedDefault`: an entry may omit `value` entirely
72
+ * (`collectFieldUsageEntries({ includeValues: false })` — apps that prefer
73
+ * no value transit). Only then is the entry's `matchedDefault` flag read, to
74
+ * decide the deviation bit alone. It can never create a histogram entry,
75
+ * never bypass the count-only rail, and never manufacture distinct users
76
+ * beyond the caller's own id. The once-per-field/day receipt means a lying
77
+ * client gets only one such contribution, so repeated POSTs cannot inflate
78
+ * thresholds or steer a `default` suggestion.
79
+ */
80
+ reportUsage(options?: {
81
+ entries?: FieldUsageReportEntry[];
82
+ }): Promise<FieldUsageReportResult>;
83
+ /**
84
+ * The defaults the CALLER's forms would have prefilled — the deviation
85
+ * authority. Resolved for the ambient `(tenant, user)` identity (the
86
+ * resolver's own TTL cache keeps repeat batches cheap).
87
+ *
88
+ * Ingestion is fire-and-forget, so a stored-layer read failure degrades to
89
+ * the CODE-SEED-only resolution (no db) rather than failing the request;
90
+ * `null` (both attempts failed) makes the caller drop the group.
91
+ */
92
+ private resolveDefaultsForCaller;
93
+ /**
94
+ * Counter rows within a period window (inclusive bounds, lexicographic ISO
95
+ * day comparison), optionally restricted to one tenant — the read the
96
+ * suggestion-generation job consumes.
97
+ */
98
+ listWindow(options: {
99
+ fromPeriod: string;
100
+ toPeriod?: string;
101
+ tenantId?: string | null;
102
+ }): Promise<FieldUsageCounter[]>;
103
+ /**
104
+ * Idempotent read-modify-write merge into the deterministic day bucket.
105
+ * Counters are approximate by design: concurrent cross-process merges may
106
+ * lose an increment (documented on the model), while the deterministic id
107
+ * plus the natural-key unique index keep concurrent creates converging on
108
+ * one row.
109
+ */
110
+ private mergeIntoBucket;
111
+ }
112
+ /**
113
+ * Deterministic bucket row id (the TenantUsageMetric `recordUsage` precedent):
114
+ * SHA-256 over the natural key, formatted as a v5-style UUID so the id column
115
+ * stays native UUID on PostgreSQL/DuckDB.
116
+ */
117
+ export declare function fieldUsageCounterId(tenantId: string, objectRef: string, fieldName: string, period: string): Promise<string>;
118
+ /** Deterministic receipt id for the durable once-per-day contribution rule. */
119
+ export declare function fieldUsageReportReceiptId(tenantId: string, userId: string, objectRef: string, fieldName: string, period: string): Promise<string>;
120
+ /**
121
+ * Histogram eligibility (#2051 pin): ONLY low-cardinality field types —
122
+ * `boolean` and reference ids (`foreignKey` / `crossPackageRef`). Free text
123
+ * is NEVER histogrammed, even when non-sensitive (PII risk); numeric,
124
+ * datetime, and json fields are count-only too.
125
+ */
126
+ export declare function isHistogramEligibleField(field: RegisteredFieldInfo): boolean;
127
+ /**
128
+ * Serialize one sample into a histogram key, type-checked against the field:
129
+ * booleans must be real booleans (`'true'` / `'false'` keys); reference ids
130
+ * must be STORABLE ids for the field — `isStorableReferenceId` applies the same
131
+ * native-UUID / `idType: 'text'` rule stored defaults are held to, within the
132
+ * bounded key length. Anything else is skipped (the submission still counts —
133
+ * count-only for that sample).
134
+ *
135
+ * The reference check is load-bearing, not cosmetic: recording an unstorable
136
+ * id would let an authenticated caller poison a histogram, win dominance with
137
+ * it, and produce a `default` suggestion whose write is then rejected by the
138
+ * same rule — turning a bad sample into a stuck generation candidate.
139
+ */
140
+ export declare function serializeHistogramSample(field: RegisteredFieldInfo, value: unknown): string | null;
141
+ /** Decode a histogram key back into the typed value it was recorded from. */
142
+ export declare function decodeHistogramKey(field: RegisteredFieldInfo, key: string): unknown;
143
+ //# sourceMappingURL=FieldUsageCounterCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldUsageCounterCollection.d.ts","sourceRoot":"","sources":["../../src/collections/FieldUsageCounterCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAQ,MAAM,0BAA0B,CAAC;AAMhE,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EAGlB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAShE;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAa5C;;;;;;;;;GASG;AACH,qBAsBa,2BAA4B,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IAChF,MAAM,CAAC,QAAQ,CAAC,UAAU,2BAAqB;IAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACG,WAAW,CACf,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,qBAAqB,EAAE,CAAA;KAAO,GAClD,OAAO,CAAC,sBAAsB,CAAC;IAkJlC;;;;;;;;OAQG;YACW,wBAAwB;IA4BtC;;;;OAIG;IACG,UAAU,CAAC,OAAO,EAAE;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAahC;;;;;;OAMG;YACW,eAAe;CA8C9B;AA6CD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,+EAA+E;AAC/E,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CASjB;AAiBD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAM5E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,IAAI,CAWf;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAKT"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Deterministic row ids for this package's idempotent writes (the
3
+ * `TenantUsageMetric.recordUsage` precedent).
4
+ *
5
+ * A leaf module (no package-internal imports) so both consumers — usage counter
6
+ * buckets and the global learning schedules — share one implementation. The
7
+ * output is formatted as a v5-shaped UUID so id columns stay native UUID on
8
+ * PostgreSQL/DuckDB.
9
+ */
10
+ /**
11
+ * SHA-256 over the namespaced parts, formatted as a v5-style UUID.
12
+ *
13
+ * The same parts always produce the same id, which is what turns
14
+ * "check then create" into a race-free write: concurrent creators converge on
15
+ * one primary key instead of inserting near-duplicate rows.
16
+ */
17
+ export declare function deterministicFieldsUuid(parts: readonly string[]): Promise<string>;
18
+ //# sourceMappingURL=deterministic-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deterministic-id.d.ts","sourceRoot":"","sources":["../src/deterministic-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -0,0 +1,85 @@
1
+ import { FieldUIHints, ObjectRegistry } from '@happyvertical/smrt-core';
2
+ import { FieldPolicyDelta, FieldPolicyVisibility } from './types.js';
3
+ /**
4
+ * Field map for one object, keyed by field name (includes inherited fields).
5
+ * Derived structurally from the PUBLIC `ObjectRegistry.getAllFields` return
6
+ * type — core does not export its internal `RegisteredField` name.
7
+ */
8
+ export type FieldDefinitionMap = Awaited<ReturnType<typeof ObjectRegistry.getAllFields>>;
9
+ /** One field's registered metadata, as returned by `getAllFields`. */
10
+ export type RegisteredFieldInfo = FieldDefinitionMap extends Map<string, infer F> ? F : never;
11
+ /**
12
+ * Resolve `objectRef` (qualified `@package/name:ClassName`) against the live
13
+ * registry, throwing a descriptive error when the class is unknown.
14
+ */
15
+ export declare function requireRegisteredObject(objectRef: string): void;
16
+ /** Load the full (inherited) field map for a registered objectRef. */
17
+ export declare function getObjectFieldMap(objectRef: string): Promise<FieldDefinitionMap>;
18
+ /**
19
+ * Narrow a manifest `_meta.ui` bag to the known {@link FieldUIHints} keys with
20
+ * their expected primitive types, dropping junk (mirrors the sanitization the
21
+ * web emission applies in core's `web-collections.ts`).
22
+ */
23
+ export declare function sanitizeFieldUIHints(value: unknown): FieldUIHints | undefined;
24
+ /** Security rail: `sensitive` may live top-level or under `_meta` (STI merges). */
25
+ export declare function isSensitiveField(field: RegisteredFieldInfo): boolean;
26
+ /** Security rail: `readPermission` may live top-level or under `_meta`. */
27
+ export declare function getFieldReadPermission(field: RegisteredFieldInfo): string | undefined;
28
+ export declare function isTransientField(field: RegisteredFieldInfo): boolean;
29
+ /**
30
+ * True when a registered field can receive a policy row. Keep this shared by
31
+ * the resolver and the catalog audit: otherwise a row that never resolves can
32
+ * accidentally be presented as an editable setting.
33
+ */
34
+ export declare function isPolicyAddressableField(field: RegisteredFieldInfo): boolean;
35
+ /**
36
+ * A field is required when flagged required and not explicitly nullable.
37
+ *
38
+ * `nullable` is read from BOTH the top level and `_meta` for the same reason
39
+ * `sensitive`/`readPermission`/`transient` are: registrations reach the
40
+ * registry through several paths (decorator, manifest, STI merge) and land the
41
+ * flag in either place. Checking only one side made the pair asymmetric —
42
+ * `required` was read from both while `nullable` was read from one.
43
+ */
44
+ export declare function isRequiredField(field: RegisteredFieldInfo): boolean;
45
+ /** The manifest/code default for a field, boxed; `undefined` when none. */
46
+ export declare function getCodeDefault(field: RegisteredFieldInfo): {
47
+ value: unknown;
48
+ } | undefined;
49
+ /**
50
+ * A resolved default satisfies the required-field invariant only when it is a
51
+ * value a form could actually submit: explicit `null` and the empty string do
52
+ * not count (a required text field "defaulting" to `''` is still unfilled).
53
+ */
54
+ export declare function isUsableRequiredDefault(defaultBox: {
55
+ value: unknown;
56
+ } | undefined): boolean;
57
+ /**
58
+ * Compute the code-seed visibility for every field of an object using the
59
+ * cold-start rule (#2046): with no `ui.basic` markers anywhere on the object,
60
+ * every field is `basic`; once any field is marked `basic: true`, unmarked
61
+ * fields default to `advanced` (and an explicit `basic: false` is always
62
+ * `advanced`).
63
+ */
64
+ export declare function buildCodeSeedVisibility(fields: FieldDefinitionMap): Map<string, FieldPolicyVisibility>;
65
+ /** Code-seed delta for one field (visibility supplied by the cold-start pass). */
66
+ export declare function buildCodeSeedDelta(field: RegisteredFieldInfo, visibility: FieldPolicyVisibility): FieldPolicyDelta;
67
+ /** Code-seed grouping key (`ui.group`) — not overridable by stored rows. */
68
+ export declare function getCodeSeedGroup(field: RegisteredFieldInfo): string | null;
69
+ /**
70
+ * True when a reference identifier can be stored in the field's backing
71
+ * column. Native UUID columns accept UUIDs only; `idType: 'text'` opts into
72
+ * arbitrary non-empty string identifiers. Shared by policy defaults and the
73
+ * usage histogram so a poisoned sample can never become an unwriteable
74
+ * suggestion.
75
+ */
76
+ export declare function isStorableReferenceId(field: RegisteredFieldInfo, value: unknown): value is string;
77
+ /**
78
+ * Type-check a parsed default value against the manifest field type.
79
+ *
80
+ * Explicit `null` is allowed only for optional fields (a required field with a
81
+ * null default has no usable default). Unsupported field types reject defaults
82
+ * outright (fail closed).
83
+ */
84
+ export declare function assertDefaultValueMatchesFieldType(objectRef: string, fieldName: string, field: RegisteredFieldInfo, value: unknown): void;
85
+ //# sourceMappingURL=field-definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-definitions.d.ts","sourceRoot":"","sources":["../src/field-definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,UAAU,CAAC,OAAO,cAAc,CAAC,YAAY,CAAC,CAC/C,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAC7B,kBAAkB,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa/D;AAED,sEAAsE;AACtE,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAG7B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAc7E;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEpE;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,mBAAmB,GACzB,MAAM,GAAG,SAAS,CAMpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAO5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAKnE;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,mBAAmB,GACzB;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAQhC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GACzC,OAAO,CAKT;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,kBAAkB,GACzB,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAuBpC;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,mBAAmB,EAC1B,UAAU,EAAE,qBAAqB,GAChC,gBAAgB,CAiBlB;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAE1E;AAUD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,MAAM,CAGjB;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,OAAO,GACb,IAAI,CAsEN"}
@@ -0,0 +1,46 @@
1
+ import { ExplainedObjectFieldPolicy, ResolvedObjectFieldPolicy, ResolveFieldPolicyOptions } from './types.js';
2
+ /**
3
+ * Resolve the merged field policy for `objectRef` in the given
4
+ * `(tenantId, userId)` context: code seed → app rows → tenant rows (hierarchy
5
+ * walk root → leaf) → user rows. Defaults AND visibility both resolve through
6
+ * the user tier.
7
+ *
8
+ * Results are cached per `(database, objectRef, tenantId, userId)` with a
9
+ * short TTL; `FieldPolicy.save()`/`.delete()` invalidate the object's entries.
10
+ */
11
+ export declare function resolveFieldPolicy(objectRef: string, options?: ResolveFieldPolicyOptions): Promise<ResolvedObjectFieldPolicy>;
12
+ /**
13
+ * The tenant ids whose rows participate in precedence for a tenant, root to
14
+ * leaf. Catalog code uses this instead of reimplementing inheritance-break
15
+ * handling when it decides whether an inherited override is customized.
16
+ */
17
+ export declare function resolveSurvivingTenantChainIds(tenantId: string, options?: ResolveFieldPolicyOptions): Promise<string[]>;
18
+ /**
19
+ * Explain variant: the merged result plus ordered per-layer contributions for
20
+ * each field, so the gear UI (#2049, "shows inherited base") and the control
21
+ * panel (#2050, effective-value-per-layer) never re-derive precedence.
22
+ *
23
+ * A user-layer row suppressed by an effective org lock is omitted from the
24
+ * layer list too — the listed layers always reproduce the merged result.
25
+ */
26
+ export declare function resolveFieldPolicyExplained(objectRef: string, options?: ResolveFieldPolicyOptions): Promise<ExplainedObjectFieldPolicy>;
27
+ /**
28
+ * Whether an import failure means `@happyvertical/smrt-users` is simply not
29
+ * installed (→ flat-tenant fallback) rather than installed-but-broken
30
+ * (→ rethrow, surfacing the problem instead of silently losing ancestor
31
+ * locks/defaults).
32
+ *
33
+ * The decision is made on the missing-module TARGET parsed from Node's
34
+ * `Cannot find package/module '<specifier>'` message (walking the full
35
+ * `cause` chain): only a target that IS smrt-users (or one of its subpaths)
36
+ * counts. A transitive failure INSIDE an installed smrt-users names the
37
+ * other package as the target — with the users path merely appearing as the
38
+ * importer — and therefore rethrows. `importWorkspaceModule`'s own
39
+ * source-fallback wrapper ("Failed to load @happyvertical/smrt-users for
40
+ * ...") is also accepted: it is thrown only when the users package itself
41
+ * cannot be located.
42
+ *
43
+ * Exported for direct testing; not re-exported from the package index.
44
+ */
45
+ export declare function isMissingUsersDependency(error: unknown): boolean;
46
+ //# sourceMappingURL=field-policy-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-policy-resolver.d.ts","sourceRoot":"","sources":["../src/field-policy-resolver.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,0BAA0B,EAQ1B,yBAAyB,EACzB,yBAAyB,EAE1B,MAAM,YAAY,CAAC;AAYpB;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,yBAAyB,CAAC,CAGpC;AAED;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,MAAM,EAAE,CAAC,CAInB;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,0BAA0B,CAAC,CA0JrC;AA0MD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAsBhE"}