@nbt-dev/nbt 0.1.0 → 0.1.2

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 (30) hide show
  1. package/README.md +7 -6
  2. package/dist/nbt.js +195 -422
  3. package/package.json +8 -4
  4. package/stdlib/auth/schema.nbt +6 -3
  5. package/stdlib/dns/schema.nbt +1 -1
  6. package/stdlib/ingest/schema.nbt +1 -1
  7. package/stdlib/phone/schema.nbt +1 -1
  8. package/stdlib/registry/schema.nbt +1 -1
  9. package/stdlib/secrets/schema.nbt +16 -0
  10. package/stdlib/workflows/schema.nbt +27 -0
  11. package/vendor/linux-x64/cartridges/auth/schema.nbt +6 -3
  12. package/vendor/linux-x64/cartridges/dns/schema.nbt +1 -1
  13. package/vendor/linux-x64/cartridges/ingest/schema.nbt +1 -1
  14. package/vendor/linux-x64/cartridges/phone/schema.nbt +1 -1
  15. package/vendor/linux-x64/cartridges/registry/schema.nbt +1 -1
  16. package/vendor/linux-x64/cartridges/secrets/schema.nbt +16 -0
  17. package/vendor/linux-x64/cartridges/workflows/schema.nbt +27 -0
  18. package/vendor/linux-x64/console +0 -0
  19. package/vendor/linux-x64/esbuild +0 -0
  20. package/vendor/linux-x64/nbt +0 -0
  21. package/stdlib/design/migrations/20260501210107_initial/migration.nbt +0 -19
  22. package/stdlib/design/migrations/20260501210107_initial/schema_snapshot.nbt +0 -21
  23. package/stdlib/design/migrations/20260610130000_design_system/migration.nbt +0 -50
  24. package/stdlib/design/migrations/20260610130000_design_system/schema_snapshot.nbt +0 -80
  25. package/stdlib/design/schema.nbt +0 -140
  26. package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/migration.nbt +0 -19
  27. package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/schema_snapshot.nbt +0 -21
  28. package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/migration.nbt +0 -50
  29. package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/schema_snapshot.nbt +0 -80
  30. package/vendor/linux-x64/cartridges/design/schema.nbt +0 -140
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@nbt-dev/nbt",
3
- "version": "0.1.0",
4
- "description": "The nbt CLI and console daemon for the nbt-dev console — a fixed-target OS for web development. Linux/x64 prebuilt binaries.",
3
+ "version": "0.1.2",
4
+ "description": "The nbt CLI and runtime for nbt-dev — a schema-first backend platform for web development. Linux/x64 + macOS prebuilt binaries.",
5
5
  "bin": {
6
6
  "nbt": "dist/nbt.js"
7
7
  },
8
8
  "files": [
9
9
  "dist/",
10
10
  "vendor/linux-x64/",
11
+ "vendor/darwin-arm64/",
12
+ "vendor/darwin-x64/",
11
13
  "stdlib/",
12
14
  "README.md",
13
15
  "LICENSE",
@@ -19,10 +21,12 @@
19
21
  "prepack": "node scripts/build.mjs"
20
22
  },
21
23
  "os": [
22
- "linux"
24
+ "linux",
25
+ "darwin"
23
26
  ],
24
27
  "cpu": [
25
- "x64"
28
+ "x64",
29
+ "arm64"
26
30
  ],
27
31
  "engines": {
28
32
  "node": ">=16"
@@ -67,9 +67,9 @@ entity Account {
67
67
  userId: string
68
68
  providerId: string
69
69
  password: string
70
- accessToken: string
71
- refreshToken: string
72
- idToken: string
70
+ accessToken: string @secret
71
+ refreshToken: string @secret
72
+ idToken: string @secret
73
73
  accessTokenExpiresAt: DateTime
74
74
  refreshTokenExpiresAt: DateTime
75
75
  scope: string
@@ -99,6 +99,9 @@ entity ApiKey {
99
99
  key: string
100
100
  permissions: string
101
101
  roles: string
102
+
103
+ @@index([key])
104
+ @@index([projectId])
102
105
  }
103
106
 
104
107
  # Console-operator SSH public keys. The console daemon authenticates SSH
@@ -21,7 +21,7 @@ entity DnsProvider {
21
21
  updatedAt: DateTime @updatedAt
22
22
  type: string # "cloudflare"
23
23
  label: string # user-facing name ("my CF account")
24
- apiToken: string # provider API token (stored as-is)
24
+ apiToken: string @secret # provider API token (sealed at rest)
25
25
  accountId: string # CF account_id, needed for add_zone + registrar calls (optional)
26
26
  status: string # "ACTIVE" | "INVALID" | "DISCONNECTED"
27
27
  lastCheckedAt: u64 # ms epoch — updated on connect + test
@@ -10,7 +10,7 @@ entity Endpoint {
10
10
  name: string
11
11
  slug: string
12
12
  status: string
13
- secret: string
13
+ secret: string @secret
14
14
  payloadCount: u64
15
15
  errorCount: u64
16
16
 
@@ -24,7 +24,7 @@ entity TwilioAccount {
24
24
  updatedAt: DateTime @updatedAt
25
25
  name: string # operator-facing label
26
26
  subAccountSid: string # AC... — populated by provision()
27
- authToken: string # subaccount auth token (stored as-is)
27
+ authToken: string @secret # subaccount auth token (sealed at rest)
28
28
  publicUrlBase: string # e.g. "https://acme.console.app"
29
29
  status: string # PENDING | ACTIVE | SUSPENDED | CLOSED
30
30
  retentionDays: s32 # 0 = keep message bodies forever; N = null body after N days
@@ -31,7 +31,7 @@ entity GsheetSync {
31
31
  createdAt: DateTime @default(now())
32
32
  updatedAt: DateTime @updatedAt
33
33
  spreadsheetId: string # parsed from the operator-provided sheet URL
34
- serviceAccountJson: string # SECRET — service-account key JSON
34
+ serviceAccountJson: string @secret # SECRET — service-account key JSON (sealed at rest)
35
35
  saEmail: string # service-account client_email (shown in devtools)
36
36
  intervalSeconds: u32 # poll cadence
37
37
  enabled: bool # sync on/off
@@ -0,0 +1,16 @@
1
+ # Secrets cart — storage substrate for named, per-environment config secrets
2
+ # (STRIPE_KEY, OPENAI_KEY, ...). The console daemon is the single writer
3
+ # (modules/api/secrets.jai); the generated CRUD is not the intended interface —
4
+ # operators set values via POST /_console/secrets (or `nbt secret set`).
5
+ #
6
+ # `value` is @secret: sealed (AEAD) at rest, replicated as ciphertext, and never
7
+ # returned by any read path. The row id is "<env>:<name>" so set/get are
8
+ # idempotent without a secondary index.
9
+ entity Secret {
10
+ id: string @id # "<env>:<name>"
11
+ createdAt: DateTime @default(now())
12
+ updatedAt: DateTime @updatedAt
13
+ name: string # slot name, e.g. STRIPE_KEY
14
+ env: string # "dev" | "staging" | "prod"
15
+ value: string @secret # sealed config value
16
+ }
@@ -22,14 +22,21 @@ entity WorkflowExecution {
22
22
  createdAt: DateTime @default(now())
23
23
  updatedAt: DateTime @updatedAt
24
24
  status: string # RUNNING (incl. async host call in flight) | SUSPENDED | COMPLETED | FAILED | CANCELLED
25
+ workflowId?: string # OPTIONAL caller-chosen id (Phase 9b) for start dedup; the PK stays an auto-ULID (FK-safe). Unset on cron/event/most starts.
25
26
  workflowName: string
26
27
  args?: string # JSON arguments passed to runWorkflow
27
28
  result?: string # JSON return value (COMPLETED)
28
29
  error?: string # message + stack (FAILED)
29
30
  cursor: u32
31
+ wakeAt: u64 # durable timer (Phase 9a): ms-epoch when a parked sleep is due (0 = not sleeping). The leader reconcile resumes the instance once wall-clock passes it.
32
+ parentExec?: string # child workflow (Phase 9e): the parent execution id to resume with this child's result on completion
33
+ parentSeq?: u32 # the parent's host-call ordinal awaiting this child's result
30
34
  lane?: string # fairness lane; per-lane concurrency is capped so a burst of one lane can't starve others (default "default")
31
35
  deployVersion: u32 # the bundle version this instance pins for its entire life (journal-header pin); replay always runs against this exact version
32
36
  events: WorkflowExecutionEvent[]
37
+ signals: WorkflowSignal[] # buffered signals awaiting delivery (Phase 9d)
38
+ @@unique([workflowId]) # start dedup: a provided workflowId is unique (NULLs distinct, so unset starts never collide)
39
+ @@index([workflowId])
33
40
  }
34
41
 
35
42
  # A recurring trigger: fire `workflowName` whenever the cron expression matches.
@@ -62,6 +69,26 @@ entity WorkflowEvent {
62
69
  processed: bool # set true once the leader has fired this emission's triggers
63
70
  }
64
71
 
72
+ # A durable, buffered signal for an execution (Phase 9d). A signal that arrives
73
+ # before the workflow reaches the matching wait() — or for a name other than the
74
+ # one currently awaited — is stored here instead of being rejected; when the
75
+ # workflow parks on wait(name) it drains the oldest unconsumed matching signal and
76
+ # delivers it as the wait's result. id is a ULID so unconsumed signals drain in
77
+ # arrival order. A signal that arrives WHILE parked on the matching wait is
78
+ # delivered immediately (fast path) and never buffered.
79
+ entity WorkflowSignal {
80
+ id: ulid
81
+ createdAt: DateTime @default(now())
82
+ updatedAt: DateTime @updatedAt
83
+ execution: WorkflowExecution @relation(onDelete: Cascade) # the target instance
84
+ name: string # signal name, matched against wait(name)
85
+ payload?: string # JSON value delivered as the wait result
86
+ idempotencyKey?: string # optional caller dedup key; a re-POST with the same key is a no-op
87
+ consumed: bool # set true once delivered to a wait
88
+ @@index([execution])
89
+ @@unique([idempotencyKey]) # NULLs distinct (null-skip), so unkeyed signals never collide
90
+ }
91
+
65
92
  enum WorkflowExecutionEventKind {
66
93
  HOST_CALL_INTENT # recorded BEFORE a side effect is performed (durability)
67
94
  HOST_CALL_RESULT # the resolved value of a host command (replay source)
@@ -67,9 +67,9 @@ entity Account {
67
67
  userId: string
68
68
  providerId: string
69
69
  password: string
70
- accessToken: string
71
- refreshToken: string
72
- idToken: string
70
+ accessToken: string @secret
71
+ refreshToken: string @secret
72
+ idToken: string @secret
73
73
  accessTokenExpiresAt: DateTime
74
74
  refreshTokenExpiresAt: DateTime
75
75
  scope: string
@@ -99,6 +99,9 @@ entity ApiKey {
99
99
  key: string
100
100
  permissions: string
101
101
  roles: string
102
+
103
+ @@index([key])
104
+ @@index([projectId])
102
105
  }
103
106
 
104
107
  # Console-operator SSH public keys. The console daemon authenticates SSH
@@ -21,7 +21,7 @@ entity DnsProvider {
21
21
  updatedAt: DateTime @updatedAt
22
22
  type: string # "cloudflare"
23
23
  label: string # user-facing name ("my CF account")
24
- apiToken: string # provider API token (stored as-is)
24
+ apiToken: string @secret # provider API token (sealed at rest)
25
25
  accountId: string # CF account_id, needed for add_zone + registrar calls (optional)
26
26
  status: string # "ACTIVE" | "INVALID" | "DISCONNECTED"
27
27
  lastCheckedAt: u64 # ms epoch — updated on connect + test
@@ -10,7 +10,7 @@ entity Endpoint {
10
10
  name: string
11
11
  slug: string
12
12
  status: string
13
- secret: string
13
+ secret: string @secret
14
14
  payloadCount: u64
15
15
  errorCount: u64
16
16
 
@@ -24,7 +24,7 @@ entity TwilioAccount {
24
24
  updatedAt: DateTime @updatedAt
25
25
  name: string # operator-facing label
26
26
  subAccountSid: string # AC... — populated by provision()
27
- authToken: string # subaccount auth token (stored as-is)
27
+ authToken: string @secret # subaccount auth token (sealed at rest)
28
28
  publicUrlBase: string # e.g. "https://acme.console.app"
29
29
  status: string # PENDING | ACTIVE | SUSPENDED | CLOSED
30
30
  retentionDays: s32 # 0 = keep message bodies forever; N = null body after N days
@@ -31,7 +31,7 @@ entity GsheetSync {
31
31
  createdAt: DateTime @default(now())
32
32
  updatedAt: DateTime @updatedAt
33
33
  spreadsheetId: string # parsed from the operator-provided sheet URL
34
- serviceAccountJson: string # SECRET — service-account key JSON
34
+ serviceAccountJson: string @secret # SECRET — service-account key JSON (sealed at rest)
35
35
  saEmail: string # service-account client_email (shown in devtools)
36
36
  intervalSeconds: u32 # poll cadence
37
37
  enabled: bool # sync on/off
@@ -0,0 +1,16 @@
1
+ # Secrets cart — storage substrate for named, per-environment config secrets
2
+ # (STRIPE_KEY, OPENAI_KEY, ...). The console daemon is the single writer
3
+ # (modules/api/secrets.jai); the generated CRUD is not the intended interface —
4
+ # operators set values via POST /_console/secrets (or `nbt secret set`).
5
+ #
6
+ # `value` is @secret: sealed (AEAD) at rest, replicated as ciphertext, and never
7
+ # returned by any read path. The row id is "<env>:<name>" so set/get are
8
+ # idempotent without a secondary index.
9
+ entity Secret {
10
+ id: string @id # "<env>:<name>"
11
+ createdAt: DateTime @default(now())
12
+ updatedAt: DateTime @updatedAt
13
+ name: string # slot name, e.g. STRIPE_KEY
14
+ env: string # "dev" | "staging" | "prod"
15
+ value: string @secret # sealed config value
16
+ }
@@ -22,14 +22,21 @@ entity WorkflowExecution {
22
22
  createdAt: DateTime @default(now())
23
23
  updatedAt: DateTime @updatedAt
24
24
  status: string # RUNNING (incl. async host call in flight) | SUSPENDED | COMPLETED | FAILED | CANCELLED
25
+ workflowId?: string # OPTIONAL caller-chosen id (Phase 9b) for start dedup; the PK stays an auto-ULID (FK-safe). Unset on cron/event/most starts.
25
26
  workflowName: string
26
27
  args?: string # JSON arguments passed to runWorkflow
27
28
  result?: string # JSON return value (COMPLETED)
28
29
  error?: string # message + stack (FAILED)
29
30
  cursor: u32
31
+ wakeAt: u64 # durable timer (Phase 9a): ms-epoch when a parked sleep is due (0 = not sleeping). The leader reconcile resumes the instance once wall-clock passes it.
32
+ parentExec?: string # child workflow (Phase 9e): the parent execution id to resume with this child's result on completion
33
+ parentSeq?: u32 # the parent's host-call ordinal awaiting this child's result
30
34
  lane?: string # fairness lane; per-lane concurrency is capped so a burst of one lane can't starve others (default "default")
31
35
  deployVersion: u32 # the bundle version this instance pins for its entire life (journal-header pin); replay always runs against this exact version
32
36
  events: WorkflowExecutionEvent[]
37
+ signals: WorkflowSignal[] # buffered signals awaiting delivery (Phase 9d)
38
+ @@unique([workflowId]) # start dedup: a provided workflowId is unique (NULLs distinct, so unset starts never collide)
39
+ @@index([workflowId])
33
40
  }
34
41
 
35
42
  # A recurring trigger: fire `workflowName` whenever the cron expression matches.
@@ -62,6 +69,26 @@ entity WorkflowEvent {
62
69
  processed: bool # set true once the leader has fired this emission's triggers
63
70
  }
64
71
 
72
+ # A durable, buffered signal for an execution (Phase 9d). A signal that arrives
73
+ # before the workflow reaches the matching wait() — or for a name other than the
74
+ # one currently awaited — is stored here instead of being rejected; when the
75
+ # workflow parks on wait(name) it drains the oldest unconsumed matching signal and
76
+ # delivers it as the wait's result. id is a ULID so unconsumed signals drain in
77
+ # arrival order. A signal that arrives WHILE parked on the matching wait is
78
+ # delivered immediately (fast path) and never buffered.
79
+ entity WorkflowSignal {
80
+ id: ulid
81
+ createdAt: DateTime @default(now())
82
+ updatedAt: DateTime @updatedAt
83
+ execution: WorkflowExecution @relation(onDelete: Cascade) # the target instance
84
+ name: string # signal name, matched against wait(name)
85
+ payload?: string # JSON value delivered as the wait result
86
+ idempotencyKey?: string # optional caller dedup key; a re-POST with the same key is a no-op
87
+ consumed: bool # set true once delivered to a wait
88
+ @@index([execution])
89
+ @@unique([idempotencyKey]) # NULLs distinct (null-skip), so unkeyed signals never collide
90
+ }
91
+
65
92
  enum WorkflowExecutionEventKind {
66
93
  HOST_CALL_INTENT # recorded BEFORE a side effect is performed (durability)
67
94
  HOST_CALL_RESULT # the resolved value of a host command (replay source)
Binary file
Binary file
Binary file
@@ -1,19 +0,0 @@
1
- migration initial {
2
- add_entity Design
3
- add_field Design name string default("")
4
- add_field Design slug string default("")
5
- add_field Design description string default("")
6
- add_field Design headVersionId string default("")
7
- add_field Design headVersion u32 default(0)
8
- add_unique Design [slug]
9
- add_entity DesignVersion
10
- add_field DesignVersion designId string default("")
11
- add_field DesignVersion version u32 default(0)
12
- add_field DesignVersion body document default(0)
13
- add_field DesignVersion source string default("")
14
- add_field DesignVersion note string default("")
15
- add_field DesignVersion createdBy string default("")
16
- add_field DesignVersion parseErrors string default("")
17
- add_index DesignVersion [designId]
18
- add_unique DesignVersion [designId, version]
19
- }
@@ -1,21 +0,0 @@
1
- entity Design {
2
- name: string
3
- slug: string
4
- description: string
5
- headVersionId: string
6
- headVersion: u32
7
- @@unique([slug])
8
- }
9
-
10
- entity DesignVersion {
11
- designId: string
12
- version: u32
13
- body: document
14
- source: string
15
- note: string
16
- createdBy: string
17
- parseErrors: string
18
- @@index([designId])
19
- @@unique([designId, version])
20
- }
21
-
@@ -1,50 +0,0 @@
1
- migration design_system {
2
- add_field Design designerId string default("")
3
- add_entity Designer
4
- add_field Designer name string default("")
5
- add_field Designer handle string default("")
6
- add_field Designer url string default("")
7
- add_field Designer bio string default("")
8
- add_unique Designer [handle]
9
- add_entity Token
10
- add_field Token designId string default("")
11
- add_field Token name string default("")
12
- add_field Token kind string default("")
13
- add_field Token value string default("")
14
- add_field Token darkValue string default("")
15
- add_index Token [designId]
16
- add_unique Token [designId, name]
17
- add_entity Component
18
- add_field Component designId string default("")
19
- add_field Component name string default("")
20
- add_field Component version u32 default(0)
21
- add_field Component designerId string default("")
22
- add_field Component propsSpec string default("")
23
- add_field Component notes string default("")
24
- add_index Component [designId]
25
- add_unique Component [designId, name]
26
- add_entity Block
27
- add_field Block designId string default("")
28
- add_field Block name string default("")
29
- add_field Block version u32 default(0)
30
- add_field Block designerId string default("")
31
- add_field Block components string default("")
32
- add_field Block slotsSpec string default("")
33
- add_field Block defaults string default("")
34
- add_index Block [designId]
35
- add_unique Block [designId, name]
36
- add_entity Rule
37
- add_field Rule designId string default("")
38
- add_field Rule subject string default("")
39
- add_field Rule kind string default("")
40
- add_field Rule rule string default("")
41
- add_field Rule note string default("")
42
- add_index Rule [designId]
43
- add_entity Page
44
- add_field Page designId string default("")
45
- add_field Page slug string default("")
46
- add_field Page title string default("")
47
- add_field Page blocks string default("")
48
- add_index Page [designId]
49
- add_unique Page [designId, slug]
50
- }
@@ -1,80 +0,0 @@
1
- entity Design {
2
- name: string
3
- slug: string
4
- description: string
5
- designerId: string
6
- headVersionId: string
7
- headVersion: u32
8
- @@unique([slug])
9
- }
10
-
11
- entity DesignVersion {
12
- designId: string
13
- version: u32
14
- body: document
15
- source: string
16
- note: string
17
- createdBy: string
18
- parseErrors: string
19
- @@index([designId])
20
- @@unique([designId, version])
21
- }
22
-
23
- entity Designer {
24
- name: string
25
- handle: string
26
- url: string
27
- bio: string
28
- @@unique([handle])
29
- }
30
-
31
- entity Token {
32
- designId: string
33
- name: string
34
- kind: string
35
- value: string
36
- darkValue: string
37
- @@index([designId])
38
- @@unique([designId, name])
39
- }
40
-
41
- entity Component {
42
- designId: string
43
- name: string
44
- version: u32
45
- designerId: string
46
- propsSpec: string
47
- notes: string
48
- @@index([designId])
49
- @@unique([designId, name])
50
- }
51
-
52
- entity Block {
53
- designId: string
54
- name: string
55
- version: u32
56
- designerId: string
57
- components: string
58
- slotsSpec: string
59
- defaults: string
60
- @@index([designId])
61
- @@unique([designId, name])
62
- }
63
-
64
- entity Rule {
65
- designId: string
66
- subject: string
67
- kind: string
68
- rule: string
69
- note: string
70
- @@index([designId])
71
- }
72
-
73
- entity Page {
74
- designId: string
75
- slug: string
76
- title: string
77
- blocks: string
78
- @@index([designId])
79
- @@unique([designId, slug])
80
- }
@@ -1,140 +0,0 @@
1
- # Published designs are world-readable (a site's frontend stitches itself from
2
- # them before any session exists); writes stay behind the auth gate.
3
- @public_route "GET /api/design/Design"
4
- @public_route "GET /api/design/Designer"
5
- @public_route "GET /api/design/Token"
6
- @public_route "GET /api/design/Component"
7
- @public_route "GET /api/design/Block"
8
- @public_route "GET /api/design/Rule"
9
- @public_route "GET /api/design/Page"
10
-
11
- #--- Entities ---
12
- # A Design is a named DESIGN.md file. Its body lives in DesignVersion rows so
13
- # the full revision history is preserved. Design.headVersionId points at the
14
- # latest version for O(1) current-state reads.
15
-
16
- entity Design {
17
- id: ulid
18
- createdAt: DateTime @default(now())
19
- updatedAt: DateTime @updatedAt
20
- name: string
21
- slug: string
22
- description: string
23
- designerId: string # who made this design system
24
- headVersionId: string
25
- headVersion: u32
26
-
27
- @@unique([slug])
28
- }
29
-
30
- entity DesignVersion {
31
- id: ulid
32
- createdAt: DateTime @default(now())
33
- updatedAt: DateTime @updatedAt
34
- designId: string
35
- version: u32 # domain revision counter (1, 2, 3 …)
36
- body: document @scope(designId)
37
- source: string
38
- note: string
39
- createdBy: string
40
- parseErrors: string
41
-
42
- @@index([designId])
43
- @@unique([designId, version])
44
- }
45
-
46
- #--- Design system ---
47
- # The product thesis: frontends are stitched from REAL designer-made designs.
48
- # Tokens/Components/Blocks carry designer attribution so anything rendered on a
49
- # site traces back to the person who designed it. JSON-shaped payloads
50
- # (propsSpec, slotsSpec, defaults, blocks, rule) are plain JSON strings the
51
- # renderer parses — no docstore ceremony for prototype-sized payloads.
52
-
53
- # Attribution-only profile: enough to say "this designer made X". No profile
54
- # pages, no auth linkage — just the name behind the work.
55
- entity Designer {
56
- id: ulid
57
- createdAt: DateTime @default(now())
58
- updatedAt: DateTime @updatedAt
59
- name: string # "Jane Doe"
60
- handle: string # "jane"
61
- url: string # portfolio link, may be empty
62
- bio: string
63
-
64
- @@unique([handle])
65
- }
66
-
67
- entity Token {
68
- id: ulid
69
- createdAt: DateTime @default(now())
70
- updatedAt: DateTime @updatedAt
71
- designId: string
72
- name: string # "surface/brand", "text/primary", "font/body", "space/section"
73
- kind: string # color | font | size | space | radius
74
- value: string # "#0A0A0A", "Inter", "6rem"
75
- darkValue: string # empty = same as value
76
-
77
- @@index([designId])
78
- @@unique([designId, name])
79
- }
80
-
81
- entity Component {
82
- id: ulid
83
- createdAt: DateTime @default(now())
84
- updatedAt: DateTime @updatedAt
85
- designId: string
86
- name: string # "button", "nav", "hero", "feature-card", "footer"
87
- version: u32
88
- designerId: string # real attribution — the trace-to-designer anchor
89
- propsSpec: string # JSON: [{"name":"label","type":"string","default":"..."}]
90
- notes: string
91
-
92
- @@index([designId])
93
- @@unique([designId, name])
94
- }
95
-
96
- entity Block {
97
- id: ulid
98
- createdAt: DateTime @default(now())
99
- updatedAt: DateTime @updatedAt
100
- designId: string
101
- name: string # "nav", "hero", "feature-grid", "cta", "footer"
102
- version: u32
103
- designerId: string
104
- components: string # JSON array of component names this block stitches
105
- slotsSpec: string # JSON: [{"name":"headline","type":"string"}, ...]
106
- defaults: string # JSON: default slot content
107
-
108
- @@index([designId])
109
- @@unique([designId, name])
110
- }
111
-
112
- entity Rule {
113
- id: ulid
114
- createdAt: DateTime @default(now())
115
- updatedAt: DateTime @updatedAt
116
- designId: string
117
- subject: string # block/component name, or "page"
118
- kind: string # ordering | count | pairing
119
- rule: string # machine-checkable JSON, e.g. {"first":"nav"} / {"max":1,"of":"hero"}
120
- note: string # designer's human rationale
121
-
122
- @@index([designId])
123
- }
124
-
125
- entity Page {
126
- id: ulid
127
- createdAt: DateTime @default(now())
128
- updatedAt: DateTime @updatedAt
129
- designId: string
130
- slug: string # "landing"
131
- title: string
132
- blocks: string # JSON: [{"block":"nav","props":{...}}, ...]
133
-
134
- @@index([designId])
135
- @@unique([designId, slug])
136
- }
137
-
138
- # Behavior (former Design.create/save_version/get_head/list_versions actions +
139
- # tasks/parse.nbt @task) moved to hand-written Jai over the generated ORM,
140
- # which also registers the HTTP routes.
@@ -1,19 +0,0 @@
1
- migration initial {
2
- add_entity Design
3
- add_field Design name string default("")
4
- add_field Design slug string default("")
5
- add_field Design description string default("")
6
- add_field Design headVersionId string default("")
7
- add_field Design headVersion u32 default(0)
8
- add_unique Design [slug]
9
- add_entity DesignVersion
10
- add_field DesignVersion designId string default("")
11
- add_field DesignVersion version u32 default(0)
12
- add_field DesignVersion body document default(0)
13
- add_field DesignVersion source string default("")
14
- add_field DesignVersion note string default("")
15
- add_field DesignVersion createdBy string default("")
16
- add_field DesignVersion parseErrors string default("")
17
- add_index DesignVersion [designId]
18
- add_unique DesignVersion [designId, version]
19
- }
@@ -1,21 +0,0 @@
1
- entity Design {
2
- name: string
3
- slug: string
4
- description: string
5
- headVersionId: string
6
- headVersion: u32
7
- @@unique([slug])
8
- }
9
-
10
- entity DesignVersion {
11
- designId: string
12
- version: u32
13
- body: document
14
- source: string
15
- note: string
16
- createdBy: string
17
- parseErrors: string
18
- @@index([designId])
19
- @@unique([designId, version])
20
- }
21
-