@happyvertical/smrt-education 0.57.37 → 0.57.39
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/AGENTS.md +8 -0
- package/agents/catalog-previews.md +98 -0
- package/agents/family-intake.md +97 -0
- package/dist/catalog-contracts.d.ts +2 -0
- package/dist/catalog-contracts.d.ts.map +1 -1
- package/dist/catalog-database-sync-store.d.ts.map +1 -1
- package/dist/catalog-models.d.ts +5 -0
- package/dist/catalog-models.d.ts.map +1 -1
- package/dist/catalog-preview.d.ts +63 -0
- package/dist/catalog-preview.d.ts.map +1 -0
- package/dist/catalog-read-service.d.ts +3 -0
- package/dist/catalog-read-service.d.ts.map +1 -1
- package/dist/catalog.d.ts +4 -4
- package/dist/catalog.d.ts.map +1 -1
- package/dist/chunks/{workbook-photo-service-1wcnf-Xf.js → workbook-photo-service-DCmqeWLd.js} +448 -202
- package/dist/chunks/workbook-photo-service-DCmqeWLd.js.map +1 -0
- package/dist/course-source.d.ts +2 -2
- package/dist/course-source.d.ts.map +1 -1
- package/dist/family-intake-contracts.d.ts +56 -0
- package/dist/family-intake-contracts.d.ts.map +1 -0
- package/dist/family-intake-ingestion.d.ts +29 -0
- package/dist/family-intake-ingestion.d.ts.map +1 -0
- package/dist/family-intake-models.d.ts +58 -0
- package/dist/family-intake-models.d.ts.map +1 -0
- package/dist/family-intake-service.d.ts +70 -0
- package/dist/family-intake-service.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +289 -13
- package/dist/index.js.map +1 -1
- package/dist/ingestion.d.ts +2 -0
- package/dist/ingestion.d.ts.map +1 -1
- package/dist/ingestion.js +426 -13
- package/dist/ingestion.js.map +1 -1
- package/dist/intake-original-evidence.d.ts +10 -0
- package/dist/intake-original-evidence.d.ts.map +1 -0
- package/dist/learner-service.d.ts +2 -0
- package/dist/learner-service.d.ts.map +1 -1
- package/dist/learners.d.ts +5 -5
- package/dist/learners.d.ts.map +1 -1
- package/dist/lesson-assets.d.ts +2 -2
- package/dist/lesson-assets.d.ts.map +1 -1
- package/dist/manifest.json +1447 -162
- package/dist/smrt-knowledge.json +563 -10
- package/dist/sources/public-illustrative-mathematics-adapter.d.ts +4 -2
- package/dist/sources/public-illustrative-mathematics-adapter.d.ts.map +1 -1
- package/dist/sources/public-illustrative-mathematics-parser.d.ts +5 -0
- package/dist/sources/public-illustrative-mathematics-parser.d.ts.map +1 -1
- package/dist/submission-service.d.ts +1 -1
- package/dist/submission-service.d.ts.map +1 -1
- package/dist/submissions.d.ts +7 -7
- package/dist/submissions.d.ts.map +1 -1
- package/dist/workbook-models.d.ts +8 -8
- package/dist/workbook-models.d.ts.map +1 -1
- package/dist/workbook-photo-ingestion.d.ts.map +1 -1
- package/dist/workbook-photo-models.d.ts +6 -5
- package/dist/workbook-photo-models.d.ts.map +1 -1
- package/dist/workbook-photo-service.d.ts +6 -0
- package/dist/workbook-photo-service.d.ts.map +1 -1
- package/package.json +10 -10
- package/dist/chunks/workbook-photo-service-1wcnf-Xf.js.map +0 -1
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-education",
|
|
6
|
-
"packageVersion": "0.57.
|
|
6
|
+
"packageVersion": "0.57.39",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "5c6a35e0af4e4612477d70216ad90e72b2bdaec842ee8cf11d726588dad34486",
|
|
11
|
+
"packageJson": "b7020102a3bac6fe5771314550029c5157fd9a68e47205dbe45210ea4192ff5f",
|
|
12
|
+
"agents": "f06312dca0737d6487b4f310b22b6c24b3276644e9ccaf9b7a27b71ebc1ca2ff",
|
|
13
13
|
"moduleDoc:agents/learner-service.md": "7da70d214547eb78fbf058e997599cc80ab86f5bb55748bd158a9a4b30070d3b",
|
|
14
14
|
"moduleDoc:agents/submission-service.md": "8e63b83ac84628d5e5ddacbb6a47077c0e65eee3da87518d9bf6e30fb8348336",
|
|
15
15
|
"moduleDoc:agents/workbook-service.md": "3ca3fb60d39daf76b94ec668fc19dc67aa7e090b7f44412bed5c9d92e8efaf5a",
|
|
16
16
|
"moduleDoc:agents/photo-intake.md": "3b7057201ee30b2361aad23ea52e8a55c8ed5354e7a7e4a8193b7de17ca2f0db",
|
|
17
|
-
"moduleDoc:agents/source-import.md": "30ee823589d655442bcf1abcd86a2132172065b4bc5e3c4d89b1e8b7afcc66bc"
|
|
17
|
+
"moduleDoc:agents/source-import.md": "30ee823589d655442bcf1abcd86a2132172065b4bc5e3c4d89b1e8b7afcc66bc",
|
|
18
|
+
"moduleDoc:agents/family-intake.md": "540b6d37f438496acb0208b6ac7258264e2142bce3d2f986967b7741606fe4f7",
|
|
19
|
+
"moduleDoc:agents/catalog-previews.md": "5f4e0352274009b3ce00408017a16666036d24df695a7078c27317ba4e66f0a7"
|
|
18
20
|
},
|
|
19
21
|
"exports": [
|
|
20
22
|
".",
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
"smrt"
|
|
60
62
|
],
|
|
61
63
|
"risks": [
|
|
62
|
-
"cross-package-refs:
|
|
64
|
+
"cross-package-refs:8",
|
|
63
65
|
"sensitive-fields-excluded",
|
|
64
66
|
"sti-inheritance"
|
|
65
67
|
],
|
|
@@ -282,6 +284,12 @@
|
|
|
282
284
|
"required": false,
|
|
283
285
|
"columnType": "TEXT"
|
|
284
286
|
},
|
|
287
|
+
{
|
|
288
|
+
"name": "preview",
|
|
289
|
+
"type": "text",
|
|
290
|
+
"required": false,
|
|
291
|
+
"columnType": "TEXT"
|
|
292
|
+
},
|
|
285
293
|
{
|
|
286
294
|
"name": "licenseEvidence",
|
|
287
295
|
"type": "text",
|
|
@@ -317,14 +325,27 @@
|
|
|
317
325
|
],
|
|
318
326
|
"relationships": [],
|
|
319
327
|
"methods": [
|
|
328
|
+
"getPreview",
|
|
320
329
|
"getRepresentation",
|
|
330
|
+
"setPreview",
|
|
321
331
|
"setRepresentation"
|
|
322
332
|
],
|
|
323
333
|
"methodSignatures": [
|
|
334
|
+
{
|
|
335
|
+
"name": "getPreview",
|
|
336
|
+
"returns": "CatalogPreview | undefined"
|
|
337
|
+
},
|
|
324
338
|
{
|
|
325
339
|
"name": "getRepresentation",
|
|
326
340
|
"returns": "CatalogResourceRepresentation | undefined"
|
|
327
341
|
},
|
|
342
|
+
{
|
|
343
|
+
"name": "setPreview",
|
|
344
|
+
"params": [
|
|
345
|
+
"value: CatalogPreview | undefined"
|
|
346
|
+
],
|
|
347
|
+
"returns": "void"
|
|
348
|
+
},
|
|
328
349
|
{
|
|
329
350
|
"name": "setRepresentation",
|
|
330
351
|
"params": [
|
|
@@ -335,6 +356,13 @@
|
|
|
335
356
|
],
|
|
336
357
|
"surfaces": [],
|
|
337
358
|
"withheldSurfaces": [
|
|
359
|
+
{
|
|
360
|
+
"kind": "api",
|
|
361
|
+
"operation": "getPreview",
|
|
362
|
+
"code": "api-disabled",
|
|
363
|
+
"reason": "api is disabled",
|
|
364
|
+
"objectName": "@happyvertical/smrt-education:CatalogResource"
|
|
365
|
+
},
|
|
338
366
|
{
|
|
339
367
|
"kind": "api",
|
|
340
368
|
"operation": "getRepresentation",
|
|
@@ -342,6 +370,13 @@
|
|
|
342
370
|
"reason": "api is disabled",
|
|
343
371
|
"objectName": "@happyvertical/smrt-education:CatalogResource"
|
|
344
372
|
},
|
|
373
|
+
{
|
|
374
|
+
"kind": "api",
|
|
375
|
+
"operation": "setPreview",
|
|
376
|
+
"code": "api-disabled",
|
|
377
|
+
"reason": "api is disabled",
|
|
378
|
+
"objectName": "@happyvertical/smrt-education:CatalogResource"
|
|
379
|
+
},
|
|
345
380
|
{
|
|
346
381
|
"kind": "api",
|
|
347
382
|
"operation": "setRepresentation",
|
|
@@ -741,6 +776,9 @@
|
|
|
741
776
|
{
|
|
742
777
|
"name": "save",
|
|
743
778
|
"async": true,
|
|
779
|
+
"params": [
|
|
780
|
+
"options?: SmrtSaveOptions"
|
|
781
|
+
],
|
|
744
782
|
"returns": "Promise<this>"
|
|
745
783
|
}
|
|
746
784
|
],
|
|
@@ -923,6 +961,9 @@
|
|
|
923
961
|
{
|
|
924
962
|
"name": "save",
|
|
925
963
|
"async": true,
|
|
964
|
+
"params": [
|
|
965
|
+
"options?: SmrtSaveOptions"
|
|
966
|
+
],
|
|
926
967
|
"returns": "Promise<this>"
|
|
927
968
|
}
|
|
928
969
|
],
|
|
@@ -1094,6 +1135,9 @@
|
|
|
1094
1135
|
{
|
|
1095
1136
|
"name": "save",
|
|
1096
1137
|
"async": true,
|
|
1138
|
+
"params": [
|
|
1139
|
+
"options?: SmrtSaveOptions"
|
|
1140
|
+
],
|
|
1097
1141
|
"returns": "Promise<this>"
|
|
1098
1142
|
}
|
|
1099
1143
|
],
|
|
@@ -1166,6 +1210,9 @@
|
|
|
1166
1210
|
{
|
|
1167
1211
|
"name": "save",
|
|
1168
1212
|
"async": true,
|
|
1213
|
+
"params": [
|
|
1214
|
+
"options?: SmrtSaveOptions"
|
|
1215
|
+
],
|
|
1169
1216
|
"returns": "Promise<this>"
|
|
1170
1217
|
}
|
|
1171
1218
|
],
|
|
@@ -1306,6 +1353,9 @@
|
|
|
1306
1353
|
{
|
|
1307
1354
|
"name": "save",
|
|
1308
1355
|
"async": true,
|
|
1356
|
+
"params": [
|
|
1357
|
+
"options?: SmrtSaveOptions"
|
|
1358
|
+
],
|
|
1309
1359
|
"returns": "Promise<this>"
|
|
1310
1360
|
}
|
|
1311
1361
|
],
|
|
@@ -1448,6 +1498,9 @@
|
|
|
1448
1498
|
{
|
|
1449
1499
|
"name": "save",
|
|
1450
1500
|
"async": true,
|
|
1501
|
+
"params": [
|
|
1502
|
+
"options?: SmrtSaveOptions"
|
|
1503
|
+
],
|
|
1451
1504
|
"returns": "Promise<this>"
|
|
1452
1505
|
}
|
|
1453
1506
|
],
|
|
@@ -1585,6 +1638,9 @@
|
|
|
1585
1638
|
{
|
|
1586
1639
|
"name": "save",
|
|
1587
1640
|
"async": true,
|
|
1641
|
+
"params": [
|
|
1642
|
+
"options?: SmrtSaveOptions"
|
|
1643
|
+
],
|
|
1588
1644
|
"returns": "Promise<this>"
|
|
1589
1645
|
}
|
|
1590
1646
|
],
|
|
@@ -1735,6 +1791,9 @@
|
|
|
1735
1791
|
{
|
|
1736
1792
|
"name": "save",
|
|
1737
1793
|
"async": true,
|
|
1794
|
+
"params": [
|
|
1795
|
+
"options?: SmrtSaveOptions"
|
|
1796
|
+
],
|
|
1738
1797
|
"returns": "Promise<this>"
|
|
1739
1798
|
}
|
|
1740
1799
|
],
|
|
@@ -1866,6 +1925,9 @@
|
|
|
1866
1925
|
{
|
|
1867
1926
|
"name": "save",
|
|
1868
1927
|
"async": true,
|
|
1928
|
+
"params": [
|
|
1929
|
+
"options?: SmrtSaveOptions"
|
|
1930
|
+
],
|
|
1869
1931
|
"returns": "Promise<this>"
|
|
1870
1932
|
}
|
|
1871
1933
|
],
|
|
@@ -2501,6 +2563,9 @@
|
|
|
2501
2563
|
{
|
|
2502
2564
|
"name": "save",
|
|
2503
2565
|
"async": true,
|
|
2566
|
+
"params": [
|
|
2567
|
+
"options?: SmrtSaveOptions"
|
|
2568
|
+
],
|
|
2504
2569
|
"returns": "Promise<this>"
|
|
2505
2570
|
},
|
|
2506
2571
|
{
|
|
@@ -2568,6 +2633,401 @@
|
|
|
2568
2633
|
"tags": [],
|
|
2569
2634
|
"risks": []
|
|
2570
2635
|
},
|
|
2636
|
+
{
|
|
2637
|
+
"name": "FamilyIntake",
|
|
2638
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntake",
|
|
2639
|
+
"collection": "familyintakes",
|
|
2640
|
+
"description": "Family-owned receipt, independent of learner attribution and ingestion expiry.",
|
|
2641
|
+
"tableName": "family_intakes",
|
|
2642
|
+
"packageName": "@happyvertical/smrt-education",
|
|
2643
|
+
"extends": "SmrtObject",
|
|
2644
|
+
"fields": [
|
|
2645
|
+
{
|
|
2646
|
+
"name": "tenantId",
|
|
2647
|
+
"type": "text",
|
|
2648
|
+
"required": true,
|
|
2649
|
+
"columnType": "UUID"
|
|
2650
|
+
},
|
|
2651
|
+
{
|
|
2652
|
+
"name": "itemId",
|
|
2653
|
+
"type": "text",
|
|
2654
|
+
"required": false,
|
|
2655
|
+
"columnType": "TEXT"
|
|
2656
|
+
},
|
|
2657
|
+
{
|
|
2658
|
+
"name": "actorUserId",
|
|
2659
|
+
"type": "text",
|
|
2660
|
+
"required": false,
|
|
2661
|
+
"columnType": "TEXT"
|
|
2662
|
+
},
|
|
2663
|
+
{
|
|
2664
|
+
"name": "ownerProfileId",
|
|
2665
|
+
"type": "crossPackageRef",
|
|
2666
|
+
"required": false,
|
|
2667
|
+
"related": "@happyvertical/smrt-profiles:Profile",
|
|
2668
|
+
"columnType": "UUID"
|
|
2669
|
+
},
|
|
2670
|
+
{
|
|
2671
|
+
"name": "contentDigest",
|
|
2672
|
+
"type": "text",
|
|
2673
|
+
"required": false,
|
|
2674
|
+
"columnType": "TEXT"
|
|
2675
|
+
},
|
|
2676
|
+
{
|
|
2677
|
+
"name": "sourceJson",
|
|
2678
|
+
"type": "text",
|
|
2679
|
+
"required": false,
|
|
2680
|
+
"columnType": "TEXT"
|
|
2681
|
+
}
|
|
2682
|
+
],
|
|
2683
|
+
"relationships": [
|
|
2684
|
+
{
|
|
2685
|
+
"name": "ownerProfileId",
|
|
2686
|
+
"type": "crossPackageRef",
|
|
2687
|
+
"required": false,
|
|
2688
|
+
"related": "@happyvertical/smrt-profiles:Profile",
|
|
2689
|
+
"columnType": "UUID"
|
|
2690
|
+
}
|
|
2691
|
+
],
|
|
2692
|
+
"methods": [
|
|
2693
|
+
"delete",
|
|
2694
|
+
"save"
|
|
2695
|
+
],
|
|
2696
|
+
"methodSignatures": [
|
|
2697
|
+
{
|
|
2698
|
+
"name": "delete",
|
|
2699
|
+
"async": true,
|
|
2700
|
+
"returns": "Promise<void>"
|
|
2701
|
+
},
|
|
2702
|
+
{
|
|
2703
|
+
"name": "save",
|
|
2704
|
+
"async": true,
|
|
2705
|
+
"params": [
|
|
2706
|
+
"options?: SmrtSaveOptions"
|
|
2707
|
+
],
|
|
2708
|
+
"returns": "Promise<this>"
|
|
2709
|
+
}
|
|
2710
|
+
],
|
|
2711
|
+
"tenant": {
|
|
2712
|
+
"scoped": true,
|
|
2713
|
+
"mode": "required",
|
|
2714
|
+
"field": "tenantId"
|
|
2715
|
+
},
|
|
2716
|
+
"conflictColumns": [
|
|
2717
|
+
"tenant_id",
|
|
2718
|
+
"item_id"
|
|
2719
|
+
],
|
|
2720
|
+
"surfaces": [],
|
|
2721
|
+
"withheldSurfaces": [
|
|
2722
|
+
{
|
|
2723
|
+
"kind": "api",
|
|
2724
|
+
"operation": "delete",
|
|
2725
|
+
"code": "api-disabled",
|
|
2726
|
+
"reason": "api is disabled",
|
|
2727
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntake"
|
|
2728
|
+
},
|
|
2729
|
+
{
|
|
2730
|
+
"kind": "api",
|
|
2731
|
+
"operation": "save",
|
|
2732
|
+
"code": "api-disabled",
|
|
2733
|
+
"reason": "api is disabled",
|
|
2734
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntake"
|
|
2735
|
+
}
|
|
2736
|
+
],
|
|
2737
|
+
"relationshipFeatures": [
|
|
2738
|
+
"crossPackageRef",
|
|
2739
|
+
"uuidColumns"
|
|
2740
|
+
],
|
|
2741
|
+
"tags": [],
|
|
2742
|
+
"risks": []
|
|
2743
|
+
},
|
|
2744
|
+
{
|
|
2745
|
+
"name": "FamilyIntakeCollection",
|
|
2746
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntakeCollection",
|
|
2747
|
+
"collection": "familyintakes",
|
|
2748
|
+
"tableName": "family_intakes",
|
|
2749
|
+
"packageName": "@happyvertical/smrt-education",
|
|
2750
|
+
"extends": "SmrtCollection",
|
|
2751
|
+
"fields": [],
|
|
2752
|
+
"relationships": [],
|
|
2753
|
+
"methods": [],
|
|
2754
|
+
"surfaces": [],
|
|
2755
|
+
"relationshipFeatures": [
|
|
2756
|
+
"uuidColumns"
|
|
2757
|
+
],
|
|
2758
|
+
"tags": [],
|
|
2759
|
+
"risks": []
|
|
2760
|
+
},
|
|
2761
|
+
{
|
|
2762
|
+
"name": "FamilyIntakeAsset",
|
|
2763
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntakeAsset",
|
|
2764
|
+
"displayLabelField": "name",
|
|
2765
|
+
"collection": "familyintakeassets",
|
|
2766
|
+
"description": "Sole family owner join; adoption borrows this exact immutable original.",
|
|
2767
|
+
"tableName": "family_intake_assets",
|
|
2768
|
+
"packageName": "@happyvertical/smrt-education",
|
|
2769
|
+
"extends": "SmrtObject",
|
|
2770
|
+
"fields": [
|
|
2771
|
+
{
|
|
2772
|
+
"name": "tenantId",
|
|
2773
|
+
"type": "text",
|
|
2774
|
+
"required": true,
|
|
2775
|
+
"columnType": "UUID"
|
|
2776
|
+
},
|
|
2777
|
+
{
|
|
2778
|
+
"name": "intakeId",
|
|
2779
|
+
"type": "foreignKey",
|
|
2780
|
+
"required": true,
|
|
2781
|
+
"related": "FamilyIntake",
|
|
2782
|
+
"columnType": "UUID"
|
|
2783
|
+
},
|
|
2784
|
+
{
|
|
2785
|
+
"name": "assetId",
|
|
2786
|
+
"type": "crossPackageRef",
|
|
2787
|
+
"required": false,
|
|
2788
|
+
"related": "@happyvertical/smrt-assets:Asset",
|
|
2789
|
+
"columnType": "UUID"
|
|
2790
|
+
},
|
|
2791
|
+
{
|
|
2792
|
+
"name": "name",
|
|
2793
|
+
"type": "text",
|
|
2794
|
+
"required": false,
|
|
2795
|
+
"columnType": "TEXT"
|
|
2796
|
+
},
|
|
2797
|
+
{
|
|
2798
|
+
"name": "mimeType",
|
|
2799
|
+
"type": "text",
|
|
2800
|
+
"required": false,
|
|
2801
|
+
"columnType": "TEXT"
|
|
2802
|
+
},
|
|
2803
|
+
{
|
|
2804
|
+
"name": "sha256",
|
|
2805
|
+
"type": "text",
|
|
2806
|
+
"required": false,
|
|
2807
|
+
"columnType": "TEXT"
|
|
2808
|
+
},
|
|
2809
|
+
{
|
|
2810
|
+
"name": "position",
|
|
2811
|
+
"type": "integer",
|
|
2812
|
+
"required": true,
|
|
2813
|
+
"columnType": "INTEGER",
|
|
2814
|
+
"default": 0
|
|
2815
|
+
}
|
|
2816
|
+
],
|
|
2817
|
+
"relationships": [
|
|
2818
|
+
{
|
|
2819
|
+
"name": "intakeId",
|
|
2820
|
+
"type": "foreignKey",
|
|
2821
|
+
"required": true,
|
|
2822
|
+
"related": "FamilyIntake",
|
|
2823
|
+
"columnType": "UUID"
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
"name": "assetId",
|
|
2827
|
+
"type": "crossPackageRef",
|
|
2828
|
+
"required": false,
|
|
2829
|
+
"related": "@happyvertical/smrt-assets:Asset",
|
|
2830
|
+
"columnType": "UUID"
|
|
2831
|
+
}
|
|
2832
|
+
],
|
|
2833
|
+
"methods": [
|
|
2834
|
+
"delete",
|
|
2835
|
+
"save"
|
|
2836
|
+
],
|
|
2837
|
+
"methodSignatures": [
|
|
2838
|
+
{
|
|
2839
|
+
"name": "delete",
|
|
2840
|
+
"async": true,
|
|
2841
|
+
"returns": "Promise<void>"
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
"name": "save",
|
|
2845
|
+
"async": true,
|
|
2846
|
+
"params": [
|
|
2847
|
+
"options?: SmrtSaveOptions"
|
|
2848
|
+
],
|
|
2849
|
+
"returns": "Promise<this>"
|
|
2850
|
+
}
|
|
2851
|
+
],
|
|
2852
|
+
"tenant": {
|
|
2853
|
+
"scoped": true,
|
|
2854
|
+
"mode": "required",
|
|
2855
|
+
"field": "tenantId"
|
|
2856
|
+
},
|
|
2857
|
+
"conflictColumns": [
|
|
2858
|
+
"tenant_id",
|
|
2859
|
+
"intake_id",
|
|
2860
|
+
"asset_id"
|
|
2861
|
+
],
|
|
2862
|
+
"surfaces": [],
|
|
2863
|
+
"withheldSurfaces": [
|
|
2864
|
+
{
|
|
2865
|
+
"kind": "api",
|
|
2866
|
+
"operation": "delete",
|
|
2867
|
+
"code": "api-disabled",
|
|
2868
|
+
"reason": "api is disabled",
|
|
2869
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntakeAsset"
|
|
2870
|
+
},
|
|
2871
|
+
{
|
|
2872
|
+
"kind": "api",
|
|
2873
|
+
"operation": "save",
|
|
2874
|
+
"code": "api-disabled",
|
|
2875
|
+
"reason": "api is disabled",
|
|
2876
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntakeAsset"
|
|
2877
|
+
}
|
|
2878
|
+
],
|
|
2879
|
+
"relationshipFeatures": [
|
|
2880
|
+
"crossPackageRef",
|
|
2881
|
+
"foreignKey",
|
|
2882
|
+
"uuidColumns"
|
|
2883
|
+
],
|
|
2884
|
+
"tags": [],
|
|
2885
|
+
"risks": []
|
|
2886
|
+
},
|
|
2887
|
+
{
|
|
2888
|
+
"name": "FamilyIntakeAssetCollection",
|
|
2889
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntakeAssetCollection",
|
|
2890
|
+
"collection": "familyintakeassets",
|
|
2891
|
+
"tableName": "family_intake_assets",
|
|
2892
|
+
"packageName": "@happyvertical/smrt-education",
|
|
2893
|
+
"extends": "SmrtCollection",
|
|
2894
|
+
"fields": [],
|
|
2895
|
+
"relationships": [],
|
|
2896
|
+
"methods": [],
|
|
2897
|
+
"surfaces": [],
|
|
2898
|
+
"relationshipFeatures": [
|
|
2899
|
+
"uuidColumns"
|
|
2900
|
+
],
|
|
2901
|
+
"tags": [],
|
|
2902
|
+
"risks": []
|
|
2903
|
+
},
|
|
2904
|
+
{
|
|
2905
|
+
"name": "FamilyIntakeDecision",
|
|
2906
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntakeDecision",
|
|
2907
|
+
"collection": "familyintakedecisions",
|
|
2908
|
+
"description": "Append-only attribution/adoption audit; no marks or learning outcomes.",
|
|
2909
|
+
"tableName": "family_intake_decisions",
|
|
2910
|
+
"packageName": "@happyvertical/smrt-education",
|
|
2911
|
+
"extends": "SmrtObject",
|
|
2912
|
+
"fields": [
|
|
2913
|
+
{
|
|
2914
|
+
"name": "tenantId",
|
|
2915
|
+
"type": "text",
|
|
2916
|
+
"required": true,
|
|
2917
|
+
"columnType": "UUID"
|
|
2918
|
+
},
|
|
2919
|
+
{
|
|
2920
|
+
"name": "intakeId",
|
|
2921
|
+
"type": "foreignKey",
|
|
2922
|
+
"required": true,
|
|
2923
|
+
"related": "FamilyIntake",
|
|
2924
|
+
"columnType": "UUID"
|
|
2925
|
+
},
|
|
2926
|
+
{
|
|
2927
|
+
"name": "requestKey",
|
|
2928
|
+
"type": "text",
|
|
2929
|
+
"required": false,
|
|
2930
|
+
"columnType": "TEXT"
|
|
2931
|
+
},
|
|
2932
|
+
{
|
|
2933
|
+
"name": "sequence",
|
|
2934
|
+
"type": "integer",
|
|
2935
|
+
"required": true,
|
|
2936
|
+
"columnType": "INTEGER",
|
|
2937
|
+
"default": 0
|
|
2938
|
+
},
|
|
2939
|
+
{
|
|
2940
|
+
"name": "actorUserId",
|
|
2941
|
+
"type": "text",
|
|
2942
|
+
"required": false,
|
|
2943
|
+
"columnType": "TEXT"
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
"name": "bodyJson",
|
|
2947
|
+
"type": "text",
|
|
2948
|
+
"required": false,
|
|
2949
|
+
"columnType": "TEXT"
|
|
2950
|
+
}
|
|
2951
|
+
],
|
|
2952
|
+
"relationships": [
|
|
2953
|
+
{
|
|
2954
|
+
"name": "intakeId",
|
|
2955
|
+
"type": "foreignKey",
|
|
2956
|
+
"required": true,
|
|
2957
|
+
"related": "FamilyIntake",
|
|
2958
|
+
"columnType": "UUID"
|
|
2959
|
+
}
|
|
2960
|
+
],
|
|
2961
|
+
"methods": [
|
|
2962
|
+
"delete",
|
|
2963
|
+
"save"
|
|
2964
|
+
],
|
|
2965
|
+
"methodSignatures": [
|
|
2966
|
+
{
|
|
2967
|
+
"name": "delete",
|
|
2968
|
+
"async": true,
|
|
2969
|
+
"returns": "Promise<void>"
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
"name": "save",
|
|
2973
|
+
"async": true,
|
|
2974
|
+
"params": [
|
|
2975
|
+
"options?: SmrtSaveOptions"
|
|
2976
|
+
],
|
|
2977
|
+
"returns": "Promise<this>"
|
|
2978
|
+
}
|
|
2979
|
+
],
|
|
2980
|
+
"tenant": {
|
|
2981
|
+
"scoped": true,
|
|
2982
|
+
"mode": "required",
|
|
2983
|
+
"field": "tenantId"
|
|
2984
|
+
},
|
|
2985
|
+
"conflictColumns": [
|
|
2986
|
+
"tenant_id",
|
|
2987
|
+
"intake_id",
|
|
2988
|
+
"request_key"
|
|
2989
|
+
],
|
|
2990
|
+
"surfaces": [],
|
|
2991
|
+
"withheldSurfaces": [
|
|
2992
|
+
{
|
|
2993
|
+
"kind": "api",
|
|
2994
|
+
"operation": "delete",
|
|
2995
|
+
"code": "api-disabled",
|
|
2996
|
+
"reason": "api is disabled",
|
|
2997
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntakeDecision"
|
|
2998
|
+
},
|
|
2999
|
+
{
|
|
3000
|
+
"kind": "api",
|
|
3001
|
+
"operation": "save",
|
|
3002
|
+
"code": "api-disabled",
|
|
3003
|
+
"reason": "api is disabled",
|
|
3004
|
+
"objectName": "@happyvertical/smrt-education:FamilyIntakeDecision"
|
|
3005
|
+
}
|
|
3006
|
+
],
|
|
3007
|
+
"relationshipFeatures": [
|
|
3008
|
+
"foreignKey",
|
|
3009
|
+
"uuidColumns"
|
|
3010
|
+
],
|
|
3011
|
+
"tags": [],
|
|
3012
|
+
"risks": []
|
|
3013
|
+
},
|
|
3014
|
+
{
|
|
3015
|
+
"name": "FamilyIntakeDecisionCollection",
|
|
3016
|
+
"qualifiedName": "@happyvertical/smrt-education:FamilyIntakeDecisionCollection",
|
|
3017
|
+
"collection": "familyintakedecisions",
|
|
3018
|
+
"tableName": "family_intake_decisions",
|
|
3019
|
+
"packageName": "@happyvertical/smrt-education",
|
|
3020
|
+
"extends": "SmrtCollection",
|
|
3021
|
+
"fields": [],
|
|
3022
|
+
"relationships": [],
|
|
3023
|
+
"methods": [],
|
|
3024
|
+
"surfaces": [],
|
|
3025
|
+
"relationshipFeatures": [
|
|
3026
|
+
"uuidColumns"
|
|
3027
|
+
],
|
|
3028
|
+
"tags": [],
|
|
3029
|
+
"risks": []
|
|
3030
|
+
},
|
|
2571
3031
|
{
|
|
2572
3032
|
"name": "Learner",
|
|
2573
3033
|
"qualifiedName": "@happyvertical/smrt-education:Learner",
|
|
@@ -2652,6 +3112,9 @@
|
|
|
2652
3112
|
{
|
|
2653
3113
|
"name": "save",
|
|
2654
3114
|
"async": true,
|
|
3115
|
+
"params": [
|
|
3116
|
+
"options?: SmrtSaveOptions"
|
|
3117
|
+
],
|
|
2655
3118
|
"returns": "Promise<this>"
|
|
2656
3119
|
},
|
|
2657
3120
|
{
|
|
@@ -2768,6 +3231,9 @@
|
|
|
2768
3231
|
{
|
|
2769
3232
|
"name": "save",
|
|
2770
3233
|
"async": true,
|
|
3234
|
+
"params": [
|
|
3235
|
+
"options?: SmrtSaveOptions"
|
|
3236
|
+
],
|
|
2771
3237
|
"returns": "Promise<this>"
|
|
2772
3238
|
}
|
|
2773
3239
|
],
|
|
@@ -2898,6 +3364,9 @@
|
|
|
2898
3364
|
{
|
|
2899
3365
|
"name": "save",
|
|
2900
3366
|
"async": true,
|
|
3367
|
+
"params": [
|
|
3368
|
+
"options?: SmrtSaveOptions"
|
|
3369
|
+
],
|
|
2901
3370
|
"returns": "Promise<this>"
|
|
2902
3371
|
}
|
|
2903
3372
|
],
|
|
@@ -3034,6 +3503,9 @@
|
|
|
3034
3503
|
{
|
|
3035
3504
|
"name": "save",
|
|
3036
3505
|
"async": true,
|
|
3506
|
+
"params": [
|
|
3507
|
+
"options?: SmrtSaveOptions"
|
|
3508
|
+
],
|
|
3037
3509
|
"returns": "Promise<this>"
|
|
3038
3510
|
}
|
|
3039
3511
|
],
|
|
@@ -3130,6 +3602,9 @@
|
|
|
3130
3602
|
{
|
|
3131
3603
|
"name": "save",
|
|
3132
3604
|
"async": true,
|
|
3605
|
+
"params": [
|
|
3606
|
+
"options?: SmrtSaveOptions"
|
|
3607
|
+
],
|
|
3133
3608
|
"returns": "Promise<this>"
|
|
3134
3609
|
}
|
|
3135
3610
|
],
|
|
@@ -3299,6 +3774,9 @@
|
|
|
3299
3774
|
{
|
|
3300
3775
|
"name": "save",
|
|
3301
3776
|
"async": true,
|
|
3777
|
+
"params": [
|
|
3778
|
+
"options?: SmrtSaveOptions"
|
|
3779
|
+
],
|
|
3302
3780
|
"returns": "Promise<this>"
|
|
3303
3781
|
}
|
|
3304
3782
|
],
|
|
@@ -3376,6 +3854,9 @@
|
|
|
3376
3854
|
{
|
|
3377
3855
|
"name": "save",
|
|
3378
3856
|
"async": true,
|
|
3857
|
+
"params": [
|
|
3858
|
+
"options?: SmrtSaveOptions"
|
|
3859
|
+
],
|
|
3379
3860
|
"returns": "Promise<this>"
|
|
3380
3861
|
}
|
|
3381
3862
|
],
|
|
@@ -3567,6 +4048,9 @@
|
|
|
3567
4048
|
{
|
|
3568
4049
|
"name": "save",
|
|
3569
4050
|
"async": true,
|
|
4051
|
+
"params": [
|
|
4052
|
+
"options?: SmrtSaveOptions"
|
|
4053
|
+
],
|
|
3570
4054
|
"returns": "Promise<this>"
|
|
3571
4055
|
},
|
|
3572
4056
|
{
|
|
@@ -3765,6 +4249,9 @@
|
|
|
3765
4249
|
{
|
|
3766
4250
|
"name": "save",
|
|
3767
4251
|
"async": true,
|
|
4252
|
+
"params": [
|
|
4253
|
+
"options?: SmrtSaveOptions"
|
|
4254
|
+
],
|
|
3768
4255
|
"returns": "Promise<this>"
|
|
3769
4256
|
}
|
|
3770
4257
|
],
|
|
@@ -3923,6 +4410,9 @@
|
|
|
3923
4410
|
{
|
|
3924
4411
|
"name": "save",
|
|
3925
4412
|
"async": true,
|
|
4413
|
+
"params": [
|
|
4414
|
+
"options?: SmrtSaveOptions"
|
|
4415
|
+
],
|
|
3926
4416
|
"returns": "Promise<this>"
|
|
3927
4417
|
}
|
|
3928
4418
|
],
|
|
@@ -4011,6 +4501,9 @@
|
|
|
4011
4501
|
{
|
|
4012
4502
|
"name": "save",
|
|
4013
4503
|
"async": true,
|
|
4504
|
+
"params": [
|
|
4505
|
+
"options?: SmrtSaveOptions"
|
|
4506
|
+
],
|
|
4014
4507
|
"returns": "Promise<this>"
|
|
4015
4508
|
}
|
|
4016
4509
|
],
|
|
@@ -4145,6 +4638,9 @@
|
|
|
4145
4638
|
{
|
|
4146
4639
|
"name": "save",
|
|
4147
4640
|
"async": true,
|
|
4641
|
+
"params": [
|
|
4642
|
+
"options?: SmrtSaveOptions"
|
|
4643
|
+
],
|
|
4148
4644
|
"returns": "Promise<this>"
|
|
4149
4645
|
},
|
|
4150
4646
|
{
|
|
@@ -4269,6 +4765,9 @@
|
|
|
4269
4765
|
{
|
|
4270
4766
|
"name": "save",
|
|
4271
4767
|
"async": true,
|
|
4768
|
+
"params": [
|
|
4769
|
+
"options?: SmrtSaveOptions"
|
|
4770
|
+
],
|
|
4272
4771
|
"returns": "Promise<this>"
|
|
4273
4772
|
}
|
|
4274
4773
|
],
|
|
@@ -4436,6 +4935,9 @@
|
|
|
4436
4935
|
{
|
|
4437
4936
|
"name": "save",
|
|
4438
4937
|
"async": true,
|
|
4938
|
+
"params": [
|
|
4939
|
+
"options?: SmrtSaveOptions"
|
|
4940
|
+
],
|
|
4439
4941
|
"returns": "Promise<this>"
|
|
4440
4942
|
}
|
|
4441
4943
|
],
|
|
@@ -4615,6 +5117,9 @@
|
|
|
4615
5117
|
{
|
|
4616
5118
|
"name": "save",
|
|
4617
5119
|
"async": true,
|
|
5120
|
+
"params": [
|
|
5121
|
+
"options?: SmrtSaveOptions"
|
|
5122
|
+
],
|
|
4618
5123
|
"returns": "Promise<this>"
|
|
4619
5124
|
}
|
|
4620
5125
|
],
|
|
@@ -4800,6 +5305,9 @@
|
|
|
4800
5305
|
{
|
|
4801
5306
|
"name": "save",
|
|
4802
5307
|
"async": true,
|
|
5308
|
+
"params": [
|
|
5309
|
+
"options?: SmrtSaveOptions"
|
|
5310
|
+
],
|
|
4803
5311
|
"returns": "Promise<this>"
|
|
4804
5312
|
}
|
|
4805
5313
|
],
|
|
@@ -4982,6 +5490,9 @@
|
|
|
4982
5490
|
{
|
|
4983
5491
|
"name": "save",
|
|
4984
5492
|
"async": true,
|
|
5493
|
+
"params": [
|
|
5494
|
+
"options?: SmrtSaveOptions"
|
|
5495
|
+
],
|
|
4985
5496
|
"returns": "Promise<this>"
|
|
4986
5497
|
}
|
|
4987
5498
|
],
|
|
@@ -5141,6 +5652,9 @@
|
|
|
5141
5652
|
{
|
|
5142
5653
|
"name": "save",
|
|
5143
5654
|
"async": true,
|
|
5655
|
+
"params": [
|
|
5656
|
+
"options?: SmrtSaveOptions"
|
|
5657
|
+
],
|
|
5144
5658
|
"returns": "Promise<this>"
|
|
5145
5659
|
}
|
|
5146
5660
|
],
|
|
@@ -5286,6 +5800,9 @@
|
|
|
5286
5800
|
{
|
|
5287
5801
|
"name": "save",
|
|
5288
5802
|
"async": true,
|
|
5803
|
+
"params": [
|
|
5804
|
+
"options?: SmrtSaveOptions"
|
|
5805
|
+
],
|
|
5289
5806
|
"returns": "Promise<this>"
|
|
5290
5807
|
}
|
|
5291
5808
|
],
|
|
@@ -5363,6 +5880,13 @@
|
|
|
5363
5880
|
"related": "Learner",
|
|
5364
5881
|
"columnType": "UUID"
|
|
5365
5882
|
},
|
|
5883
|
+
{
|
|
5884
|
+
"name": "familyIntakeId",
|
|
5885
|
+
"type": "foreignKey",
|
|
5886
|
+
"required": false,
|
|
5887
|
+
"related": "FamilyIntake",
|
|
5888
|
+
"columnType": "UUID"
|
|
5889
|
+
},
|
|
5366
5890
|
{
|
|
5367
5891
|
"name": "itemId",
|
|
5368
5892
|
"type": "text",
|
|
@@ -5389,6 +5913,13 @@
|
|
|
5389
5913
|
"required": true,
|
|
5390
5914
|
"related": "Learner",
|
|
5391
5915
|
"columnType": "UUID"
|
|
5916
|
+
},
|
|
5917
|
+
{
|
|
5918
|
+
"name": "familyIntakeId",
|
|
5919
|
+
"type": "foreignKey",
|
|
5920
|
+
"required": false,
|
|
5921
|
+
"related": "FamilyIntake",
|
|
5922
|
+
"columnType": "UUID"
|
|
5392
5923
|
}
|
|
5393
5924
|
],
|
|
5394
5925
|
"methods": [
|
|
@@ -5404,6 +5935,9 @@
|
|
|
5404
5935
|
{
|
|
5405
5936
|
"name": "save",
|
|
5406
5937
|
"async": true,
|
|
5938
|
+
"params": [
|
|
5939
|
+
"options?: SmrtSaveOptions"
|
|
5940
|
+
],
|
|
5407
5941
|
"returns": "Promise<this>"
|
|
5408
5942
|
}
|
|
5409
5943
|
],
|
|
@@ -5556,6 +6090,9 @@
|
|
|
5556
6090
|
{
|
|
5557
6091
|
"name": "save",
|
|
5558
6092
|
"async": true,
|
|
6093
|
+
"params": [
|
|
6094
|
+
"options?: SmrtSaveOptions"
|
|
6095
|
+
],
|
|
5559
6096
|
"returns": "Promise<this>"
|
|
5560
6097
|
}
|
|
5561
6098
|
],
|
|
@@ -5695,6 +6232,9 @@
|
|
|
5695
6232
|
{
|
|
5696
6233
|
"name": "save",
|
|
5697
6234
|
"async": true,
|
|
6235
|
+
"params": [
|
|
6236
|
+
"options?: SmrtSaveOptions"
|
|
6237
|
+
],
|
|
5698
6238
|
"returns": "Promise<this>"
|
|
5699
6239
|
}
|
|
5700
6240
|
],
|
|
@@ -5828,6 +6368,9 @@
|
|
|
5828
6368
|
{
|
|
5829
6369
|
"name": "save",
|
|
5830
6370
|
"async": true,
|
|
6371
|
+
"params": [
|
|
6372
|
+
"options?: SmrtSaveOptions"
|
|
6373
|
+
],
|
|
5831
6374
|
"returns": "Promise<this>"
|
|
5832
6375
|
}
|
|
5833
6376
|
],
|
|
@@ -5885,14 +6428,14 @@
|
|
|
5885
6428
|
"surfaces": [],
|
|
5886
6429
|
"prompts": [],
|
|
5887
6430
|
"relationshipsV2": {
|
|
5888
|
-
"foreignKeyFields":
|
|
5889
|
-
"crossPackageRefFields":
|
|
6431
|
+
"foreignKeyFields": 73,
|
|
6432
|
+
"crossPackageRefFields": 8,
|
|
5890
6433
|
"junctionCollections": 2,
|
|
5891
6434
|
"hierarchicalObjects": 0,
|
|
5892
6435
|
"polymorphicAssociations": 0,
|
|
5893
|
-
"uuidColumns":
|
|
6436
|
+
"uuidColumns": 320
|
|
5894
6437
|
},
|
|
5895
|
-
"agentDoc": "# smrt-education\n\nCatalog objects are optional-tenant scoped and have no generated REST, CLI, MCP,\nor AI surface. Applications use `CatalogService`, supplying their actor-bound\nauthorization decision and the trusted `TenantCollection.withTenantCatalogReadScope`\nadapter from smrt-users. Catalog authorization receives the exact shared collection\nexecutor; live session/permission checks must use that executor. That read scope may widen only an allowlisted catalog\ncollection's `list` to self, ancestors, and globals; it never authorizes a get,\nwrite, raw query, sibling, or descendant read.\n\n`personal-use-copy` courses and all `answer-key` lesson assets are private\nfamily material. Do not publish them, promote them, or expose them through a\nlearner-facing result. `LessonAsset` is the sole owner join for lesson files;\ndo not add asset-id fields to lesson subclasses.\n\nLearner objects require exact tenant ownership and close generated surfaces.\n`LearnerService` owns actor/resource authorization and transactional planning and\nstart-progress; see [learner contract](agents/learner-service.md). Guardian\nrelationships require a host decision about their type and effective terms.\nNever expose direct collection writes as learner handlers, reset progress on a\nretry, or treat an unscored nullable decimal as zero.\n\nSubmission capture, guardian grading and private PDF packet splitting use\n`SubmissionService`; see [submission contract](agents/submission-service.md).\nKeep asset metadata on the same transaction and compensate only newly planned\nfiles after rollback; never expose source URIs or accept learner grade patches.\n\nValidation: `pnpm --filter @happyvertical/smrt-education test`,\n`test:postgres`, `typecheck`, and `build`.\n\nPhysical workbook capture, immutable assessment/feedback history and descriptive\nevidence use [WorkbookService](agents/workbook-service.md). Keep provisional\nsharing separate from guardian Grade authority. Photo-first receipt/context\ncapture uses [WorkbookPhotoService](agents/photo-intake.md); covers/references\nnever create learning evidence, and blank exercises need explicit work intent.\n\nSource import: [host boundary and transaction contract](agents/source-import.md).\n`SourceImportService` requires host opt-in, matching active actor/tenant and\nexplicit licensing authorization; never add a system/global write bypass.\n",
|
|
6438
|
+
"agentDoc": "# smrt-education\n\nCatalog objects are optional-tenant scoped and have no generated REST, CLI, MCP,\nor AI surface. Applications use `CatalogService`, supplying their actor-bound\nauthorization decision and the trusted `TenantCollection.withTenantCatalogReadScope`\nadapter from smrt-users. Catalog authorization receives the exact shared collection\nexecutor; live session/permission checks must use that executor. That read scope may widen only an allowlisted catalog\ncollection's `list` to self, ancestors, and globals; it never authorizes a get,\nwrite, raw query, sibling, or descendant read.\n\n`personal-use-copy` courses and all `answer-key` lesson assets are private\nfamily material. Do not publish them, promote them, or expose them through a\nlearner-facing result. `LessonAsset` is the sole owner join for lesson files;\ndo not add asset-id fields to lesson subclasses.\n\nLearner objects require exact tenant ownership and close generated surfaces.\n`LearnerService` owns actor/resource authorization and transactional planning and\nstart-progress; see [learner contract](agents/learner-service.md). Guardian\nrelationships require a host decision about their type and effective terms.\nNever expose direct collection writes as learner handlers, reset progress on a\nretry, or treat an unscored nullable decimal as zero.\n\nSubmission capture, guardian grading and private PDF packet splitting use\n`SubmissionService`; see [submission contract](agents/submission-service.md).\nKeep asset metadata on the same transaction and compensate only newly planned\nfiles after rollback; never expose source URIs or accept learner grade patches.\n\nValidation: `pnpm --filter @happyvertical/smrt-education test`,\n`test:postgres`, `typecheck`, and `build`.\n\nPhysical workbook capture, immutable assessment/feedback history and descriptive\nevidence use [WorkbookService](agents/workbook-service.md). Keep provisional\nsharing separate from guardian Grade authority. Photo-first receipt/context\ncapture uses [WorkbookPhotoService](agents/photo-intake.md); covers/references\nnever create learning evidence, and blank exercises need explicit work intent.\n\nSource import: [host boundary and transaction contract](agents/source-import.md).\n`SourceImportService` requires host opt-in, matching active actor/tenant and\nexplicit licensing authorization; never add a system/global write bypass.\n\nFamily-owned unassigned originals and audited learner adoption use\n[FamilyIntakeService](agents/family-intake.md). Keep family source scope immutable;\nassignment alone never creates learning history or grants learner inbox access.\n\nPublisher catalog previews use [the preview contract](agents/catalog-previews.md).\nKeep independent image rights and source revisions; serve via `CatalogPreviewService`\nwith live actor/tenant authorization, never direct provider image URLs.\n",
|
|
5896
6439
|
"moduleDocs": [
|
|
5897
6440
|
{
|
|
5898
6441
|
"path": "agents/learner-service.md",
|
|
@@ -5918,6 +6461,16 @@
|
|
|
5918
6461
|
"path": "agents/source-import.md",
|
|
5919
6462
|
"module": "source-import",
|
|
5920
6463
|
"content": "# Source import integration\n\n`SourceImportService` is a server-side host boundary, with no generated REST,\nCLI, MCP or AI operation. Recipes remain metadata only. Provision a closed\n`CourseSource` in the owning tenant, then construct the service with the root\nSQL database and an actor-bound `SourceImportAuthorizer`. Enable tenancy and\ncall within `withTenant({ tenantId, userId })`; the request must match both.\nMissing context, a different actor/tenant and super-admin bypass fail closed.\n\nRegister Easy Peasy only after the host operator accepts its terms, using\n`registerEasyPeasy({ termsAccepted: true, fetchPage })`. Do not derive that\nboolean from an HTTP request. `fetchPage(url, { redirect: 'error' })` must reject\nredirects, bound time/size and return `{ html, url }`. It fetches the page only,\nnever a PDF. The service checks the approved HTTPS URL before fetching, checks\nthe response URL, limits HTML to 2 million characters, then parses the complete\npage before any write. There is no automatic registration or network access. Structural h1–h6 headings delimit day content, including trailing Resources\nsections; ordinary non-lesson bold instructions do not. Supported\nheading blocks are h1–h6 or a lesson marker as the first bold run in a\nparagraph/list item.\nRecognizable markers outside that layout, including multiple markers in one\nparagraph, fail closed rather than silently assigning a PDF to the wrong day.\n\nThe authorizer must verify the authenticated actor's management grant and the\nprovisioned tenant's family/group classification. Tenant has no built-in kind;\nneither hierarchy position nor client input establishes a family. Authorization\nis required before fetch and again inside the transaction; callbacks must be\nread-only decisions, since a rolled-back contention retry can call them again.\n\n`sharing` is a ceiling: private permits private-family import only; group and\nglobal permit private-family or group import. Group imports additionally require\nnonblank host-recorded `config.licenseEvidence` and an explicit host grant that\nvalidates that permission. Global/null destinations are unsupported and rejected;\nthere is no global/system bypass. Widening a source never promotes existing\nimports. Private imports are draft `personal-use-copy` courses and retain the\ncatalog's immutable owner/license and no-publication protection. A host may\ncreate a new licensed group source and import there after receiving permission.\n\nUse a stable `courseRef` independent of source URLs. Identities derive from the\nowning tenant, source row ID, course reference and lesson day; retain the source\nrow when updating policy. Changes to titles/page/PDF URLs update in place.\nMissing days are retained, not deleted, so enrollment, progress, submission and\nasset foreign keys remain valid. A changed lesson kind fails the whole import\nrather than replacing a row. Only title and pointer fields are refreshed; body,\nanswer keys, learner state and manually authored settings are never replaced.\nThe packet URL is returned as a source link and is not downloaded or mirrored.\n\nAll source policy rechecks and catalog mutations use collections bound to the\nsame SQL transaction. Embedded writes use the public write queue; PostgreSQL\nserializes an import identity with a transaction-scoped advisory lock. Only\nrolled-back busy/serialization/deadlock errors retry (at most three retries),\nwithout repeating fetch. Connection-invalidated and other failures propagate.\nDo not wrap the service in a caller transaction if the caller expects a durable\ncommit before returning; any outer transaction remains the caller's boundary.\n\nSQLite and PostgreSQL integration tests exercise real transactions and rollback.\nFull catalog children remain unavailable on DuckDB due to core's existing\nON UPDATE CASCADE/self-referential schema limitations documented in\n[catalog-service.md](catalog-service.md); no alternate schema is substituted.\nTests use synthetic local HTML and an injected fetch callback, never the network.\n\nGoogle Drive discovery defaults every record to `teacher`. A trusted host may\nmake only an exact reviewed file ID visible by passing `studentSafeFileIds`;\nfolder IDs and descendant membership never grant visibility. A teacher-marked\nfolder or name still wins over that allowlist. File shortcuts are excluded: a\nshortcut does not prove the target remains under a reviewed root or retains the\ntarget's teacher-path classification. Resync after changing the allowlist: the\ndurable sync upsert rewrites existing visibility rather than retaining a\nprevious learner classification.\n\nGeneric “Printable” and “Printables” labels identify lesson PDFs; course packets\nrequire explicit packet/whole-course/complete-course wording. Only actual href\nattributes supply pointers; data-href metadata does not.\n"
|
|
6464
|
+
},
|
|
6465
|
+
{
|
|
6466
|
+
"path": "agents/family-intake.md",
|
|
6467
|
+
"module": "family-intake",
|
|
6468
|
+
"content": "# Family intake\n\n`FamilyIntakeService` retains guardian-only originals before a learner is known.\nThe host supplies a trusted actor/tenant and a current family authorizer; each\nread, original download, assignment and adoption revalidates this authority on\nthe service's exact executor. Learners cannot browse the family inbox. Generated\nCRUD, CLI, MCP and AI surfaces remain closed.\n\nRetain the whole document with its source identity, delivery key, immutable hash\nand original private assets. Source delivery retries must preserve identical\ncontent and provenance. Email and scanner adapters are separate host configuration;\nthis service does not configure or select them. Trusted candidate DTOs and their\nquoted evidence are advisory. A guardian's active learner preference, visible\nmarks, uncertain names or a first-page guess never establish ownership. Mixed\nlearner PDFs stay unresolved until an explicit whole-document assignment is safe.\n\nAssignment records an immutable guardian decision with a revision and request\nkey. It does not create learner work. Adoption freezes that assignment and borrows\nthe exact original assets through learner photo ownership joins; it never rewrites\nsource confidentiality or creates grades. The existing photo resolution and\ncompleted-work capture preconditions still apply. Existing derived capture copies\nare permitted. Once adopted, a receipt cannot silently change learners; recovery\nrequires a separate explicit policy. An unadopted attribution can be corrected by\nanother audited decision with the current revision.\n\nFamily ownership retains originals beyond generic receipt expiry. Adoption does\nnot transfer or delete that ownership. Cleanup and rollback must preserve shared\nretained bytes and compensate only newly created files. Every access checks the\noriginal hash before adoption or download.\n\nValidation uses shared family workflows on real SQLite and isolated PostgreSQL;\nno AI providers, scanner/email services or containers are required.\n\nImport `FamilyIntakeService`, `receiveFamilyIntake` and\n`retainFamilyIntakeReceipt` from `@happyvertical/smrt-education/ingestion`.\nThe bridge uses the fixed `familyIntakeScopeId(tenantId)` namespace and public\n`getReceiptSource` to retain authoritative delivery identity. This namespace is\nnever an authorization grant. The host's `IngestionService.authorize` callback\nmust call the same current family authorizer on every operation, including direct\n`getEvidence`, `readEvidence` and `getReceiptSource` calls. For example, await\n`family.authorizeFamilyIntake({ tenantId: scope.tenantId, actorUserId: scope.actorId })`\nthen return true; propagate denial. Actor equality or tenant membership alone is\ninsufficient. This protects raw envelopes and rejected/unretained originals as\nwell as adopted receipts. Adoption permits only normal authorized learner work\nreads; it never grants the learner generic family ingestion access. A receive that\nsucceeds before education retention fails is repaired by retrying the same\nreceipt, never by inventing another delivery identity.\n\nDeploy manifest migrations for all three FamilyIntake models and the nullable\n`WorkbookPhotoIntake.familyIntakeId` FK before use. There is no runtime DDL.\nAdoption commits its immutable audit and exact photo/original joins atomically;\nthe family asset remains the sole original owner. Existing derived submission\ncopies use normal capture compensation. The exact adoption audit is required\nwhen validating borrowing joins, reads and immutable family-scope analysis.\n`countFamilyIntakes` counts unadopted receipts across the full inbox, while\n`listFamilyIntakes` pages the complete receipt history.\n\nAfter adoption, use the returned `photoIntakeId` with ordinary photo\nresolution/capture methods. Family-scope photo analysis checks the exact adopted\nitem/learner binding; learner-scoped uploads retain their existing strict scope.\nThe existing submission/assessment ingestion handlers still revalidate the\ncaptured learner/attempt. Temporary ingestion expiry does not prevent manual\nresolution/capture from retained education originals; re-analysis of an expired\nreceipt needs a separately authorized retained-input orchestration.\n\nThis initial contract assigns a whole receipt/document. It does not split a\nmixed-child PDF, automatically infer a child or configure a source adapter.\nFuture range adoption must preserve original hashes and page provenance; the\nretained immutable originals remain available for such an explicit workflow.\n\nSource-tree retention includes image/PDF attachments beneath metadata envelopes.\nA supported-media descendant of another supported original (for example a PDF's\npage thumbnail) stays in the evidence graph but is not duplicated as learner\nwork. Photo identification and captured-work analysis preservation use this same\noriginal-selection convention, so retained attachment hashes remain authoritative\nafter adoption and retries. The immutable graph retains only IDs, parent IDs, media types and hashes;\nit does not copy email bodies, arbitrary headers or credentials into public\nsource metadata. A source image such as an email logo is not automatically\nclassified as completed work. Whole-document attribution/classification remains\nan explicit guardian decision; ambiguous mixed contents need resolution.\n\nCustom source adapters must follow this supported convention: metadata parents\ncontain independent original attachments; descendants of supported media are\nrenditions of that media. Extraction outputs already live separately from source\nevidence. An adapter that uses media-child relationships for independently\nauthored attachments is unsupported by this bridge until its role is explicitly\nestablished; do not claim complete attachment fidelity for that shape or infer\nroles from first-page content. Full immutable evidence lineage is retained even\nwhen a rendition is excluded from capture pages.\n\nThe bridge rejects an entire receipt containing an unsupported independent\noriginal, including a mixed PDF/TIFF bundle, before family retention. Generic\nsource originals remain available for recovery; no partial family receipt or\nadoption is created. Hosts must acknowledge successful family import only after\nfamily retention succeeds and surface failed source imports. Known JSON\nmetadata wrappers and media descendants under the supported rendition convention\nare not independent originals.\n"
|
|
6469
|
+
},
|
|
6470
|
+
{
|
|
6471
|
+
"path": "agents/catalog-previews.md",
|
|
6472
|
+
"module": "catalog-previews",
|
|
6473
|
+
"content": "# Publisher catalog previews\n\n`CatalogSourceRecord.preview` and `CatalogResourceView.preview` are optional\n`CatalogPreview` metadata. They describe a publisher image, not an acquired\noriginal, cover guarantee, download permission, or learner access grant. The\npublic root exports `CatalogPreviewService`, `CatalogPreviewStore`,\n`CatalogPreviewLoader`, `catalogPreviewFor`, and `normalizeCatalogPreview`.\n`CatalogResource.getPreview()` reads the guarded persisted JSON. Deploy the normal\nadditive manifest migration for its nullable `preview` column before sync; legacy\nrows have no preview. Sync retains the first retrieval timestamp on identical\nrevision retries and rejects changing an existing preview within that revision.\nNew revisions replace the current reference; old revision requests become 404.\nPNG verification resolves its Node host capability only when invoked; importing\ncatalog metadata/models remains browser-safe. Serving/verification requires a\nNode host and fails closed without it.\nThe image hash participates in the IM page record's revision, so changed bytes\ncannot silently reuse a preview revision.\n\nThe public IM first-edition adapter automatically selects at most one embedded\ninstructional diagram on a K–5 family-materials page. It requires that exact\npage's CC BY 4.0 footer and attribution, an official ImageFile figure with an\nempty caption, no separate credits or image-license notice in the instructional\ncontent, a descriptive chart/diagram alt, and an exact official asset identifier.\nBranding, photographs, credited or ambiguous images, other providers, unsupported\nformats and missing metadata remain absent. This narrow page-scoped policy does\nnot grant a provider-wide image license. The source footer explicitly excludes\nthe name/logo and preserves third-party image licenses; never remove those\nexclusions or apply this rule to arbitrary images. Existing teacher visibility\nis retained, including family hierarchy records currently classified teacher.\n\nConcrete publisher evidence, retrieved 2026-10-28:\n[Grade 1 Unit 1 Family Materials](https://im.kendallhunt.com/k5/families/grade-1/unit-1/family-materials.html)\nembeds ImageFile 38531, “Tally Chart. Turtle, tallies, 6. Dog, tallies, 2.\nRabbit, tallies, 12.” Its\n[official PNG](https://cms-assets.illustrativemathematics.org/fd1cykl2wl4zyfc6vzfkl3x09pvr)\nis 93,072 bytes, 1350 × 674. The licensed instructional fragment and PNG are\nfixtures in `src/__tests__/fixtures/im-family-*`, attributed to © 2021\nIllustrative Mathematics, CC BY 4.0. The image is unmodified. Captions or separate\nattribution appearing in a future sync make the preview unavailable.\n\nEnumeration performs metadata reads and at most one **preview image** GET per\npage; it never GETs original PDFs/ZIPs. It accepts only official HTTPS origin and\nopaque path, refuses redirects, and bounds the complete network/body operation\nby the adapter deadline (20 seconds default, 60 maximum). Required HTML/HEAD\nwork completes before optional sync previews, which get an independent deadline\nof one quarter of that budget, capped at two seconds and the remaining total\nenumeration budget. A hung preview cannot pause\nmetadata enumeration or its cursor. PNG previews have a\n2 MiB byte cap and 4096-pixel width/height cap. SVG, HTML, JPEG and other formats\nare currently unavailable. Only non-interlaced, static 8-bit RGB/RGBA PNGs are\nverified: complete chunks/CRCs/IEND and bounded inflated scanlines must be valid;\ntruncated or corrupt data never becomes a verified preview. This uses existing provider request bounds rather\nthan a general URL proxy. A preview failure leaves catalog metadata readable.\n`CatalogReadService.search()` performs no image or content fetches.\n\nWire a host endpoint using only the published root API:\n\n```ts\nimport {\n CatalogPreviewService,\n createPublicIllustrativeMathematicsFirstEditionAdapter,\n} from '@happyvertical/smrt-education';\n\nconst previews = new CatalogPreviewService({\n // Both functions use your trusted active-session/tenant executor. Adapt your\n // persisted resource to CatalogSourceRecord, including row.getPreview().\n getResource: (id, actor) => catalogStore.getReadableResource(id, actor),\n authorize: (actor, resource) => catalogPolicy.canReadNow(actor, resource.id),\n}, createPublicIllustrativeMathematicsFirstEditionAdapter());\n\n// Inside GET /catalog/preview; actor is derived from the server session.\nreturn previews.serve({ actor, resourceId, revision });\n```\n\nRender your own endpoint URL only when `view.preview` is present, using `alt`,\nwidth/height and rights attribution. Never place `reference` or `sourceUrl` into\nan image URL. The endpoint re-reads the current resource and checks active\nhost authorization, tenant/actor identity, teacher visibility, withdrawal,\nrevision and optional rights expiry on **every request**, including cache hits.\nThe host must check actor membership/active tenant, not merely trust strings in a\nrequest. Do not expose an unscoped collection read as this adapter.\n\nRights expiry is checked again after awaited loading/verification and before\nserving or inserting cached bytes. The per-service cache holds at most 16 MiB of verified public image bytes for at\nmost 60 seconds; reuse a service instance to benefit from it. Cache lookup occurs\nafter authorization. Changed length, dimensions or SHA-256, expiry, missing or\ninvalid metadata, upstream failures and access denial yield uniform 404 with\n`Cache-Control: no-store`; successful responses are PNG, `nosniff`, sandboxed,\nand `private, no-store`, so browsers cannot serve a revoked preview from cache.\nNo credential, upstream image URL, redirect or raw provider error reaches the\nbrowser. Synchronize regularly to observe publisher withdrawal/license changes;\nserver byte caching never bypasses the durable current-resource decision.\n\nPrivate asset previews and derivatives of acquired originals are unavailable in\nthis publisher-only contract. Use the asset authority and the separate acquired\noriginal derivative capability (#4470), with authorization on every private\nasset read. Possessing an asset, granting full-resource download/print, or being\nable to view a publisher page never supplies preview permission here.\n"
|
|
5921
6474
|
}
|
|
5922
6475
|
],
|
|
5923
6476
|
"recipes": [
|