01. Record model
Draft 0.1. Reference implementation: frontend/src/utils/timeline.js, frontend/src/services/familyVaultService.js, frontend/src/pages/TranscriptBuilderPage.jsx, api/publish-transcript.js.
1.1 The shape in one paragraph
A Record belongs to one person (the learner) and is held by that person's family, which acts as the records office of record. It is made of entries: things that happened (a book, a project, a course, volunteer hours, a mentor session, a competition, a job, an ESA purchase, an attempt). Some entries are assembled into a Witness Transcript™, a transcript of courses, the receipt (tr_) a family issues to a receiver. Any entry, course, note, or curated wall can be sealed into a content-addressed receipt (chapter 02). Adults outside the family can put their name on a receipt through a witness attestation (chapter 03). The family's device holds the content; the public ledger holds only the metadata a receiver needs to check a printed or shared artifact.
1.2 Persons
A person is a row in the family vault. The reference implementation encrypts the person's content on device (familyVaultService.js, _enc: 'wcv1') and keeps three fields in the clear for indexing.
| name | type | required | meaning |
|---|---|---|---|
id | string | yes | Stable identifier for the person within the family. Appears on receipts as person_id. |
familyId | string | yes | The family the person belongs to. |
role | string | yes | Free string; default 'family-member'. The Record does not enumerate roles and MUST NOT treat role as an authorization claim. |
A person's content (name, dates, documents) never enters a public receipt except as the surface fields the family chooses to print (chapter 02, per-prefix hash domains).
1.3 Entries (the private timeline, tl_)
Entries are captured on device by appendEntry and stored under the person. An entry's identifier begins with tl_ and is private: it is not hashed, not published, and not verifiable on its own (chapter 02, section 2.2). An entry becomes public only when it is sealed into a ws_ receipt.
kind MUST be one of the closed enum KINDS:
| kind | meaning |
|---|---|
book | book read or audiobook completed |
project | self-directed project shipped |
course | course or unit completed |
volunteer | volunteer hours or community work |
mentor | mentor session, tutoring, 1:1 with a coach |
competition | competition entered or placed |
job | paid work |
esa_expense | ESA-funded purchase (compliance metadata only) |
attempt | a try or iteration; in a portfolio, failures never subtract |
Entry fields:
| name | type | required | meaning |
|---|---|---|---|
id | string | yes | tl_<base36 time>_<6 random>; private, never hashed |
person_id | string or null | yes | owner person |
kind | enum | yes | see above |
title | string | yes | trimmed, non-empty |
detail | string or null | no | free text; stays on device |
evidence_url | string or null | no | inline or external evidence reference (v1 seal) |
evidence_sha256 | 64 hex or null | no | content hash of evidence held in the encrypted evidence store (v2 seal) |
evidence_mime, evidence_thumb | string or null | no | on-device display only; never hashed |
at | ISO 8601 | yes | when it happened |
created_at | ISO 8601 | yes | when it was captured; never hashed |
hours, instruction_days, subjects[], state_code | number, number, string[], string; all nullable | no | compliance metadata for jurisdiction plugins (chapter 08); never in any hash domain |
category, amount, educational_purpose | string or null | no | esa_expense only; amount is the string the family typed, not a normalized number |
Normative rules:
- An implementation MUST refuse an unknown
kindand an emptytitle. - An implementation MUST NOT send
detail,evidence_thumb, or compliance metadata to any public surface. Only the sealed subset (chapter 02) leaves the device. - The relationship vocabulary
RELATIONSHIPS(tutor, coach, teacher, mentor, supervisor, employer, peer, parent) is an optional chip set for capture surfaces. Free text remains valid everywhere it is accepted, and the enum is outside every hash domain.
1.4 Courses and the transcript
A transcript is a list of course rows assembled by the family in the transcript builder and sealed into one tr_ receipt plus one cr_ receipt per course row that carries the minimum fields.
Course row as authored:
| name | type | required | meaning |
|---|---|---|---|
year | string | no | e.g. 2025-26 |
term | string | yes for cr_ | e.g. Year, Fall |
subject | string | no | builder label (English, Mathematics, ...); read by jurisdiction plugins |
title | string | yes for cr_ | course title |
credit | string | no | as typed; 1.0 and 1 are different strings by design |
grade | string | yes for cr_ | as issued by the family |
evidence | string | no | free text pointer; stays on device |
tier | enum | yes | self, family, mentor, receiver; the family's own description of the row's source (chapter 03, section 3.6) |
The tr_ receipt hashes the whole issuance payload (student block, all course rows, issuance time, issuer account, person id); the cr_ receipt hashes only the identity-bearing tuple of one row (chapter 02, section 2.4). The two are related by provenance (tr_receipt_id on the cr_ row), never by hash.
1.5 Work samples, notes, walls
Three further sealable objects exist beyond courses. Their constitutional differences are stamped into the verify payload as transcript_eligible:
| object | prefix | transcript_eligible | who authors | notes |
|---|---|---|---|---|
| work sample (a sealed entry) | ws_ | not stamped; may be cited as evidence and may be witnessed | family | title, kind, issuer, dates, has_evidence go public; detail and evidence stay on device |
| weekly note (reflection) | wn_ | false | the learner (author is fixed to kid inside the hash) | never witnessed; excerpt of at most 140 characters goes public; body stays on device; no view tracking |
| wall (curated surface) | wl_ | false | learner or family (curator) | at most 50 pins, ws_ and wn_ only; identity fixed at creation, mutable snapshot hash per re-curation; no view tracking |
1.6 The family as records office of record
The Record inverts the default: the family issues, the school (when there is one) is a witness. Concretely:
- The public
issuerstring on atr_/ws_receipt is chosen by the family (the gold demo usesChen Family Records Office). - Publishing a transcript to the public ledger REQUIRES a signed-in family account; the server pins
issuer_userfrom the verified session token and ignores any client-supplied issuer (api/publish-transcript.js). A guest MAY seal locally, and the receipt then verifies only on the issuing device. - The family may revoke any receipt it issued (
tr_,cr_,ws_,wn_,wl_); a revoked receipt is served as WITHDRAWN, never as a 404 (chapter 03, section 3.7). - The record is free to the family. Optional compliance artifacts (chapter 08) may be paid; the record itself is not.
1.7 The issuer concept
An issuer is the party whose account publishes a receipt and whose key (chapter 04) signs it.
| issuer kind | status | how it appears |
|---|---|---|
| family | built | issuer_user = the family account; issuer = the family-chosen display string; family key did:key signs the leaf when signing is enabled |
| organization (a school, network, or independent counselor issuing on a learner's behalf) | planned (gap: no organization-issued tr_/cr_/ws_ path exists; organizations today exist only as receivers, counselors, and witnesses) | would carry an organization key, an organization kb_ binding, and an issuer identity level; specified in a later draft once the issuer rail exists |
An organization that witnesses a course today does so through chapter 03, not by issuing.
1.8 What this does not prove
The Record model proves structure, not truth. A person row proves nothing about identity. An entry proves that the family captured a claim on a date. A course row proves that the family wrote a title, a term, a grade, and a credit; the tier chip is the family's description of where the claim came from, and no backend enforces it (chapter 03, section 3.6). None of this, by itself, proves that any third party evaluated the work. That is what witnesses (chapter 03) and, later, issuer identity levels are for.