@happyvertical/smrt-education 0.57.37 → 0.57.38

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 (47) hide show
  1. package/AGENTS.md +4 -0
  2. package/agents/family-intake.md +97 -0
  3. package/dist/catalog.d.ts +4 -4
  4. package/dist/catalog.d.ts.map +1 -1
  5. package/dist/chunks/{workbook-photo-service-1wcnf-Xf.js → workbook-photo-service-DCmqeWLd.js} +448 -202
  6. package/dist/chunks/workbook-photo-service-DCmqeWLd.js.map +1 -0
  7. package/dist/course-source.d.ts +2 -2
  8. package/dist/course-source.d.ts.map +1 -1
  9. package/dist/family-intake-contracts.d.ts +56 -0
  10. package/dist/family-intake-contracts.d.ts.map +1 -0
  11. package/dist/family-intake-ingestion.d.ts +29 -0
  12. package/dist/family-intake-ingestion.d.ts.map +1 -0
  13. package/dist/family-intake-models.d.ts +58 -0
  14. package/dist/family-intake-models.d.ts.map +1 -0
  15. package/dist/family-intake-service.d.ts +70 -0
  16. package/dist/family-intake-service.d.ts.map +1 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +5 -5
  20. package/dist/index.js.map +1 -1
  21. package/dist/ingestion.d.ts +2 -0
  22. package/dist/ingestion.d.ts.map +1 -1
  23. package/dist/ingestion.js +426 -13
  24. package/dist/ingestion.js.map +1 -1
  25. package/dist/intake-original-evidence.d.ts +10 -0
  26. package/dist/intake-original-evidence.d.ts.map +1 -0
  27. package/dist/learner-service.d.ts +2 -0
  28. package/dist/learner-service.d.ts.map +1 -1
  29. package/dist/learners.d.ts +5 -5
  30. package/dist/learners.d.ts.map +1 -1
  31. package/dist/lesson-assets.d.ts +2 -2
  32. package/dist/lesson-assets.d.ts.map +1 -1
  33. package/dist/manifest.json +1319 -78
  34. package/dist/smrt-knowledge.json +524 -10
  35. package/dist/submission-service.d.ts +1 -1
  36. package/dist/submission-service.d.ts.map +1 -1
  37. package/dist/submissions.d.ts +7 -7
  38. package/dist/submissions.d.ts.map +1 -1
  39. package/dist/workbook-models.d.ts +8 -8
  40. package/dist/workbook-models.d.ts.map +1 -1
  41. package/dist/workbook-photo-ingestion.d.ts.map +1 -1
  42. package/dist/workbook-photo-models.d.ts +6 -5
  43. package/dist/workbook-photo-models.d.ts.map +1 -1
  44. package/dist/workbook-photo-service.d.ts +6 -0
  45. package/dist/workbook-photo-service.d.ts.map +1 -1
  46. package/package.json +8 -8
  47. package/dist/chunks/workbook-photo-service-1wcnf-Xf.js.map +0 -1
package/AGENTS.md CHANGED
@@ -37,3 +37,7 @@ never create learning evidence, and blank exercises need explicit work intent.
37
37
  Source import: [host boundary and transaction contract](agents/source-import.md).
38
38
  `SourceImportService` requires host opt-in, matching active actor/tenant and
39
39
  explicit licensing authorization; never add a system/global write bypass.
40
+
41
+ Family-owned unassigned originals and audited learner adoption use
42
+ [FamilyIntakeService](agents/family-intake.md). Keep family source scope immutable;
43
+ assignment alone never creates learning history or grants learner inbox access.
@@ -0,0 +1,97 @@
1
+ # Family intake
2
+
3
+ `FamilyIntakeService` retains guardian-only originals before a learner is known.
4
+ The host supplies a trusted actor/tenant and a current family authorizer; each
5
+ read, original download, assignment and adoption revalidates this authority on
6
+ the service's exact executor. Learners cannot browse the family inbox. Generated
7
+ CRUD, CLI, MCP and AI surfaces remain closed.
8
+
9
+ Retain the whole document with its source identity, delivery key, immutable hash
10
+ and original private assets. Source delivery retries must preserve identical
11
+ content and provenance. Email and scanner adapters are separate host configuration;
12
+ this service does not configure or select them. Trusted candidate DTOs and their
13
+ quoted evidence are advisory. A guardian's active learner preference, visible
14
+ marks, uncertain names or a first-page guess never establish ownership. Mixed
15
+ learner PDFs stay unresolved until an explicit whole-document assignment is safe.
16
+
17
+ Assignment records an immutable guardian decision with a revision and request
18
+ key. It does not create learner work. Adoption freezes that assignment and borrows
19
+ the exact original assets through learner photo ownership joins; it never rewrites
20
+ source confidentiality or creates grades. The existing photo resolution and
21
+ completed-work capture preconditions still apply. Existing derived capture copies
22
+ are permitted. Once adopted, a receipt cannot silently change learners; recovery
23
+ requires a separate explicit policy. An unadopted attribution can be corrected by
24
+ another audited decision with the current revision.
25
+
26
+ Family ownership retains originals beyond generic receipt expiry. Adoption does
27
+ not transfer or delete that ownership. Cleanup and rollback must preserve shared
28
+ retained bytes and compensate only newly created files. Every access checks the
29
+ original hash before adoption or download.
30
+
31
+ Validation uses shared family workflows on real SQLite and isolated PostgreSQL;
32
+ no AI providers, scanner/email services or containers are required.
33
+
34
+ Import `FamilyIntakeService`, `receiveFamilyIntake` and
35
+ `retainFamilyIntakeReceipt` from `@happyvertical/smrt-education/ingestion`.
36
+ The bridge uses the fixed `familyIntakeScopeId(tenantId)` namespace and public
37
+ `getReceiptSource` to retain authoritative delivery identity. This namespace is
38
+ never an authorization grant. The host's `IngestionService.authorize` callback
39
+ must call the same current family authorizer on every operation, including direct
40
+ `getEvidence`, `readEvidence` and `getReceiptSource` calls. For example, await
41
+ `family.authorizeFamilyIntake({ tenantId: scope.tenantId, actorUserId: scope.actorId })`
42
+ then return true; propagate denial. Actor equality or tenant membership alone is
43
+ insufficient. This protects raw envelopes and rejected/unretained originals as
44
+ well as adopted receipts. Adoption permits only normal authorized learner work
45
+ reads; it never grants the learner generic family ingestion access. A receive that
46
+ succeeds before education retention fails is repaired by retrying the same
47
+ receipt, never by inventing another delivery identity.
48
+
49
+ Deploy manifest migrations for all three FamilyIntake models and the nullable
50
+ `WorkbookPhotoIntake.familyIntakeId` FK before use. There is no runtime DDL.
51
+ Adoption commits its immutable audit and exact photo/original joins atomically;
52
+ the family asset remains the sole original owner. Existing derived submission
53
+ copies use normal capture compensation. The exact adoption audit is required
54
+ when validating borrowing joins, reads and immutable family-scope analysis.
55
+ `countFamilyIntakes` counts unadopted receipts across the full inbox, while
56
+ `listFamilyIntakes` pages the complete receipt history.
57
+
58
+ After adoption, use the returned `photoIntakeId` with ordinary photo
59
+ resolution/capture methods. Family-scope photo analysis checks the exact adopted
60
+ item/learner binding; learner-scoped uploads retain their existing strict scope.
61
+ The existing submission/assessment ingestion handlers still revalidate the
62
+ captured learner/attempt. Temporary ingestion expiry does not prevent manual
63
+ resolution/capture from retained education originals; re-analysis of an expired
64
+ receipt needs a separately authorized retained-input orchestration.
65
+
66
+ This initial contract assigns a whole receipt/document. It does not split a
67
+ mixed-child PDF, automatically infer a child or configure a source adapter.
68
+ Future range adoption must preserve original hashes and page provenance; the
69
+ retained immutable originals remain available for such an explicit workflow.
70
+
71
+ Source-tree retention includes image/PDF attachments beneath metadata envelopes.
72
+ A supported-media descendant of another supported original (for example a PDF's
73
+ page thumbnail) stays in the evidence graph but is not duplicated as learner
74
+ work. Photo identification and captured-work analysis preservation use this same
75
+ original-selection convention, so retained attachment hashes remain authoritative
76
+ after adoption and retries. The immutable graph retains only IDs, parent IDs, media types and hashes;
77
+ it does not copy email bodies, arbitrary headers or credentials into public
78
+ source metadata. A source image such as an email logo is not automatically
79
+ classified as completed work. Whole-document attribution/classification remains
80
+ an explicit guardian decision; ambiguous mixed contents need resolution.
81
+
82
+ Custom source adapters must follow this supported convention: metadata parents
83
+ contain independent original attachments; descendants of supported media are
84
+ renditions of that media. Extraction outputs already live separately from source
85
+ evidence. An adapter that uses media-child relationships for independently
86
+ authored attachments is unsupported by this bridge until its role is explicitly
87
+ established; do not claim complete attachment fidelity for that shape or infer
88
+ roles from first-page content. Full immutable evidence lineage is retained even
89
+ when a rendition is excluded from capture pages.
90
+
91
+ The bridge rejects an entire receipt containing an unsupported independent
92
+ original, including a mixed PDF/TIFF bundle, before family retention. Generic
93
+ source originals remain available for recovery; no partial family receipt or
94
+ adoption is created. Hosts must acknowledge successful family import only after
95
+ family retention succeeds and surface failed source imports. Known JSON
96
+ metadata wrappers and media descendants under the supported rendition convention
97
+ are not independent originals.
package/dist/catalog.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SmrtObject } from '@happyvertical/smrt-core';
1
+ import { SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
2
2
  export type CourseLicenseKind = 'own-work' | 'open-license' | 'personal-use-copy' | 'licensed-for-sharing';
3
3
  export type CourseModality = 'online' | 'printable' | 'kit' | 'video' | 'game' | 'mixed';
4
4
  export type CourseStatus = 'draft' | 'published' | 'archived';
@@ -25,7 +25,7 @@ export declare class Course extends SmrtObject {
25
25
  status: CourseStatus;
26
26
  constructor(options?: Record<string, unknown>);
27
27
  /** A personal copy remains pinned to its original family and license. */
28
- save(): Promise<this>;
28
+ save(options?: SmrtSaveOptions): Promise<this>;
29
29
  }
30
30
  export declare class ExternalCourse extends Course {
31
31
  }
@@ -37,7 +37,7 @@ export declare class CourseSection extends SmrtObject {
37
37
  title: string;
38
38
  sortOrder: number;
39
39
  constructor(options?: Record<string, unknown>);
40
- save(): Promise<this>;
40
+ save(options?: SmrtSaveOptions): Promise<this>;
41
41
  }
42
42
  export declare class Lesson extends SmrtObject {
43
43
  tenantId: string | null;
@@ -52,7 +52,7 @@ export declare class Lesson extends SmrtObject {
52
52
  externalRef: string;
53
53
  externalUrl: string;
54
54
  constructor(options?: Record<string, unknown>);
55
- save(): Promise<this>;
55
+ save(options?: SmrtSaveOptions): Promise<this>;
56
56
  }
57
57
  export declare class Reading extends Lesson {
58
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,cAAc,GACd,mBAAmB,GACnB,sBAAsB,CAAC;AAC3B,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,WAAW,GACX,KAAK,GACL,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AACZ,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;AAC9D,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAwB9E,qBAEa,MAAO,SAAQ,UAAU;IACN,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClC,KAAK,SAAM;IACtC,OAAO,SAAM;IACb,WAAW,SAAM;IACjB,SAAS,SAAY;IACrB,SAAS,SAAM;IACf,SAAS,SAAM;IACf,OAAO,SAAM;IACb,WAAW,EAAE,iBAAiB,CAAc;IAC5C,WAAW,SAAM;IACjB,UAAU,SAAM;IAChB,OAAO,SAAM;IACb,IAAI,SAAM;IACV,QAAQ,SAAK;IACb,QAAQ,SAAK;IACb,UAAU,SAAO;IACjB,gBAAgB,SAAK;IACrB,QAAQ,EAAE,cAAc,CAAY;IACpC,MAAM,EAAE,YAAY,CAAW;gBACnB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAKjD,yEAAyE;IAC1D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAyCrC;AAED,qBACa,cAAe,SAAQ,MAAM;CAAG;AAE7C,qBACa,cAAe,SAAQ,MAAM;CAAG;AAE7C,qBAEa,aAAc,SAAQ,UAAU;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnB,QAAQ,SAAM;IAC7B,KAAK,SAAM;IACtC,SAAS,SAAK;gBACF,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBrC;AAED,qBAEa,MAAO,SAAQ,UAAU;IACN,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACZ,SAAS,SAAM;IACrC,KAAK,SAAM;IACtC,IAAI,SAAM;IACV,SAAS,SAAK;IACd,gBAAgB,SAAK;IACrB,UAAU,SAAO;IACjB,QAAQ,EAAE,cAAc,CAAY;IACpC,cAAc,EAAE,oBAAoB,CAAY;IAChD,WAAW,SAAM;IACjB,WAAW,SAAM;gBACL,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBrC;AAED,qBACa,OAAQ,SAAQ,MAAM;CAAG;AACtC,qBACa,KAAM,SAAQ,MAAM;IAC/B,QAAQ,SAAM;gBACF,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAIlD;AACD,qBACa,SAAU,SAAQ,MAAM;IACnC,YAAY,SAAM;IAClB,SAAS,SAAM;IACf,KAAK,SAAK;IACD,cAAc,EAAE,oBAAoB,CAAY;gBAC7C,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAIlD;AACD,qBACa,QAAS,SAAQ,MAAM;CAAG"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,UAAU,EACV,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,cAAc,GACd,mBAAmB,GACnB,sBAAsB,CAAC;AAC3B,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,WAAW,GACX,KAAK,GACL,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AACZ,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;AAC9D,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAwB9E,qBAEa,MAAO,SAAQ,UAAU;IACN,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClC,KAAK,SAAM;IACtC,OAAO,SAAM;IACb,WAAW,SAAM;IACjB,SAAS,SAAY;IACrB,SAAS,SAAM;IACf,SAAS,SAAM;IACf,OAAO,SAAM;IACb,WAAW,EAAE,iBAAiB,CAAc;IAC5C,WAAW,SAAM;IACjB,UAAU,SAAM;IAChB,OAAO,SAAM;IACb,IAAI,SAAM;IACV,QAAQ,SAAK;IACb,QAAQ,SAAK;IACb,UAAU,SAAO;IACjB,gBAAgB,SAAK;IACrB,QAAQ,EAAE,cAAc,CAAY;IACpC,MAAM,EAAE,YAAY,CAAW;gBACnB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAKjD,yEAAyE;IAC1D,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAyC9D;AAED,qBACa,cAAe,SAAQ,MAAM;CAAG;AAE7C,qBACa,cAAe,SAAQ,MAAM;CAAG;AAE7C,qBAEa,aAAc,SAAQ,UAAU;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnB,QAAQ,SAAM;IAC7B,KAAK,SAAM;IACtC,SAAS,SAAK;gBACF,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAmB9D;AAED,qBAEa,MAAO,SAAQ,UAAU;IACN,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACZ,SAAS,SAAM;IACrC,KAAK,SAAM;IACtC,IAAI,SAAM;IACV,SAAS,SAAK;IACd,gBAAgB,SAAK;IACrB,UAAU,SAAO;IACjB,QAAQ,EAAE,cAAc,CAAY;IACpC,cAAc,EAAE,oBAAoB,CAAY;IAChD,WAAW,SAAM;IACjB,WAAW,SAAM;gBACL,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAmB9D;AAED,qBACa,OAAQ,SAAQ,MAAM;CAAG;AACtC,qBACa,KAAM,SAAQ,MAAM;IAC/B,QAAQ,SAAM;gBACF,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAIlD;AACD,qBACa,SAAU,SAAQ,MAAM;IACnC,YAAY,SAAM;IAClB,SAAS,SAAM;IACf,KAAK,SAAK;IACD,cAAc,EAAE,oBAAoB,CAAY;gBAC7C,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAIlD;AACD,qBACa,QAAS,SAAQ,MAAM;CAAG"}