Data model (MER)¶
Generated from source — do not edit
Emitted by scripts/gen_data_model_docs.py from the live
Kernel.auto() registry and the SQLAlchemy table model.
scripts/data_model_guard.py fails CI when this page and a
fresh regeneration disagree. Edit the generator, never this file.
DNA's data model has two levels. The logical model — Kinds and the references between them — carries the meaning. The physical model is a generic document store that tells you almost nothing about the domain, and this page says so rather than dressing it up.
One database, four schema owners¶
A MER showing only the SDK's tables and stopping there misleads by omission. A single Postgres instance is shared by four independent schema owners, each migrating only its own tables:
| Owner | Migrates | On this page |
|---|---|---|
| DNA SDK (this repo) | the document-store tables below, via its own Alembic tree | yes — fully |
| dna-cloud portal | its Prisma schema (accounts, plans, billing — real relational tables with real foreign keys) | no — separate repo, separate migration tool |
| Copilot service | copilot_thread and friends |
no |
| LangGraph runtime | checkpoint* / store* |
no |
The SDK's Alembic run is explicitly told not to have opinions about tables it does not own — otherwise autogenerate would propose dropping another owner's data. That exclusion list is machine- readable, so it is reproduced from source rather than asserted:
| Excluded from the SDK's autogenerate |
|---|
alembic_version |
dna_schema_migrations |
dna_search_docs |
dna_search_meta |
dna_search_migrations |
schema_migrations |
search_docs |
search_fts |
search_meta |
search_vec |
sqlite_sequence |
Logical model — Kinds and their references¶
80 Kinds are registered. Each is a document, not a table: a Kind costs a YAML descriptor and zero migrations, which is the point of an open type system. The cost is that references between Kinds are not database foreign keys — they are fields holding a name.
How to read the edges¶
Not every line here is equally trustworthy, and pretending otherwise would be the whole problem. Four tiers, strongest first:
| Tier | Drawn | What it means |
|---|---|---|
| Declared | solid | The field carries x-dna-ref. The kernel resolves it at write time — the only tier the system enforces. |
Composition (dep) |
solid | dep_filters names the target Kind. A real declaration, but it drives prompt composition and is never checked against stored data. |
| Inferred | dashed | Nothing declares it; the field NAME resolves to a Kind. A convention, not a contract. |
| Unresolved | not drawn | Reference-shaped, no confident target. Tabulated below. |
* on a label marks a polymorphic reference (several possible target Kinds).
108 edges: 15 declared, 66 composition-only, 27 inferred — plus 23 reference-shaped fields left unresolved and 6 known-undeclarable ones.
Only the declared tier cannot dangle
dep_filters declares a target Kind; nothing validates the
value. A Feature.owner naming an Actor that does not exist is
written without complaint. Solid therefore means "the model knows
what this points at", not "this resolves". Closing that gap is
what x-dna-ref does, one field at a time.
Overview — how the groups reference each other¶
Kinds are grouped by alias prefix (sdlc-, helix-, …) — a grouping
that comes from the data. Arrows are counts of edges between groups;
self-references are omitted here and shown in the detail diagrams.
flowchart LR
agentskills["agentskills (1 Kind)"]
audit["audit (2 Kinds)"]
dna["dna (2 Kinds)"]
eval["eval (4 Kinds)"]
evidence["evidence (2 Kinds)"]
guardrails["guardrails (1 Kind)"]
helix["helix (13 Kinds)"]
intel["intel (2 Kinds)"]
kinddef["kinddef (1 Kind)"]
lesson["lesson (1 Kind)"]
mif["mif (1 Kind)"]
portfolio["portfolio (5 Kinds)"]
presidio["presidio (1 Kind)"]
research["research (1 Kind)"]
sdlc["sdlc (25 Kinds)"]
soulspec["soulspec (1 Kind)"]
tenant["tenant (6 Kinds)"]
testkit["testkit (2 Kinds)"]
agentskills -->|1| sdlc
audit -->|2| portfolio
evidence -->|1| eval
evidence -->|1| sdlc
helix -->|2| agentskills
helix -->|2| guardrails
helix -->|1| portfolio
helix -->|1| presidio
helix -->|1| sdlc
helix -->|2| soulspec
kinddef -->|1| dna
lesson -->|1| agentskills
sdlc -->|1| evidence
sdlc -->|13| helix
sdlc -->|1| intel
sdlc -->|1| mif
sdlc -->|1| research
tenant -->|1| portfolio
testkit -->|1| evidence
Detail by group¶
All 80 Kinds in one diagram is an unreadable hairball, so each group with at least 2 edges gets its own. A group carrying more than 20 edges is split again by tier, which keeps the enforced edges legible instead of losing them among the unvalidated ones. A box from another group appearing here is a cross-group reference.
audit (2 edges)¶
erDiagram
AuditLog
Role
UserRoleAssignment
AuditLog }o..}o Role : "roles (inferred)"
UserRoleAssignment }o..}o Role : "roles (inferred)"
eval (3 edges)¶
erDiagram
EvalBaseline
EvalCase
EvalRun
EvalSuite
EvalBaseline }o..|| EvalSuite : "suite (inferred)"
EvalRun }o..|| EvalSuite : "suite (inferred)"
EvalSuite }o--}o EvalCase : "cases (dep)"
evidence (2 edges)¶
erDiagram
EvalSuite
Evidence
EvidencePolicy
WorkflowEvent
Evidence }o..|| EvalSuite : "suite (inferred)"
EvidencePolicy }o..}o WorkflowEvent : "events (inferred)"
helix (15 edges)¶
erDiagram
Actor
Agent
Guardrail
PromptTemplate
Recognizer
Role
SafetyPolicy
Skill
Soul
Tool
UseCase
Actor }o..|| Role : "role (inferred)"
Agent }o--|| Actor : "actors (dep)"
Agent }o--}o Guardrail : "guardrails (dep)"
Agent }o..|| PromptTemplate : "promptTemplate (inferred)"
Agent }o--}o Skill : "skills (dep)"
Agent }o--|| Soul : "soul (dep)"
Agent }o--}o Tool : "tools (dep)"
SafetyPolicy }o--}o Recognizer : "recognizers (dep)"
UseCase }o--}o Agent : "agents (dep)"
UseCase }o--}o Guardrail : "guardrails (dep)"
UseCase }o--|| Actor : "primary_actor (dep)"
UseCase }o--}o Skill : "skills (dep)"
UseCase }o--|| Soul : "soul (dep)"
UseCase }o--}o Actor : "supporting_actors (dep)"
UseCase }o--}o Tool : "tools (dep)"
portfolio (4 edges)¶
erDiagram
Membership
Organization
Project
Repo
Membership }o--|| Organization : "scope_ref *"
Membership }o--|| Project : "scope_ref *"
Project }o--|| Organization : "org_ref"
Project }o--}o Repo : "repo_refs"
sdlc — declared (11 edges)¶
erDiagram
Epic
Feature
Plan
Spec
Story
Task
Epic }o--}o Feature : "features"
Feature }o--|| Epic : "epic"
Feature }o--}o Story : "stories"
Plan }o--|| Epic : "epic"
Plan }o--|| Spec : "spec_ref"
Spec }o--|| Epic : "epic"
Spec }o--|| Spec : "supersedes"
Story }o--}o Story : "dependencies"
Story }o--|| Feature : "feature"
Story }o--}o Spec : "spec_refs"
Task }o--|| Story : "story_ref"
sdlc — composition (52 edges)¶
erDiagram
ADR
Actor
AgentSession
Bug
Epic
Feature
Initiative
Issue
Kaizen
Narrative
Plan
Postmortem
Reference
Retrospective
RiskRegister
Roadmap
Spec
Spike
Story
Task
UseCase
WorkflowEvent
ADR }o--}o Feature : "covers_features (dep)"
ADR }o--|| ADR : "superseded_by (dep)"
ADR }o--}o ADR : "supersedes (dep)"
AgentSession }o--}o Actor : "participants (dep)"
Bug }o--|| ADR : "fix_adr (dep)"
Bug }o--|| Feature : "related_feature (dep)"
Bug }o--|| Story : "related_story (dep)"
Feature }o--|| Actor : "owner (dep)"
Feature }o--}o UseCase : "use_cases (dep)"
Initiative }o--}o Epic : "epics (dep)"
Initiative }o--|| Actor : "owner (dep)"
Issue }o--|| Actor : "owner (dep)"
Issue }o--|| Feature : "related_feature (dep)"
Kaizen }o--|| Issue : "issue (dep)"
Narrative }o--}o Epic : "covers_epics (dep)"
Narrative }o--}o Feature : "covers_features (dep)"
Narrative }o--}o Story : "covers_stories (dep)"
Postmortem }o--}o Feature : "related_features (dep)"
Postmortem }o--}o Story : "related_stories (dep)"
Retrospective }o--}o Epic : "covers_epics (dep)"
Retrospective }o--}o Feature : "covers_features (dep)"
Retrospective }o--|| AgentSession : "covers_session (dep)"
Retrospective }o--}o Story : "covers_stories (dep)"
RiskRegister }o--|| Actor : "owner (dep)"
RiskRegister }o--}o Epic : "related_epics (dep)"
RiskRegister }o--}o Feature : "related_features (dep)"
Roadmap }o--|| Epic : "epics (dep)"
Spike }o--|| Feature : "feature (dep)"
Spike }o--|| ADR : "follow_up_adr (dep)"
Spike }o--|| Spec : "follow_up_spec (dep)"
Spike }o--|| Story : "follow_up_story (dep)"
Spike }o--}o Reference : "references (dep)"
Spike }o--}o Spike : "related_spikes (dep)"
Story }o--|| Actor : "owner (dep)"
Task }o--|| Actor : "owner (dep)"
WorkflowEvent }o--|| AgentSession : "parent_ref (dep) *"
WorkflowEvent }o--|| Epic : "parent_ref (dep) *"
WorkflowEvent }o--|| Feature : "parent_ref (dep) *"
WorkflowEvent }o--|| Narrative : "parent_ref (dep) *"
WorkflowEvent }o--|| Plan : "parent_ref (dep) *"
WorkflowEvent }o--|| Roadmap : "parent_ref (dep) *"
WorkflowEvent }o--|| Spec : "parent_ref (dep) *"
WorkflowEvent }o--|| Story : "parent_ref (dep) *"
WorkflowEvent }o--|| AgentSession : "ref (dep) *"
WorkflowEvent }o--|| Epic : "ref (dep) *"
WorkflowEvent }o--|| Feature : "ref (dep) *"
WorkflowEvent }o--|| Narrative : "ref (dep) *"
WorkflowEvent }o--|| Plan : "ref (dep) *"
WorkflowEvent }o--|| Roadmap : "ref (dep) *"
WorkflowEvent }o--|| Spec : "ref (dep) *"
WorkflowEvent }o--|| Story : "ref (dep) *"
WorkflowEvent }o--|| WorkflowEvent : "transitioned_from (dep)"
sdlc — inferred (11 edges)¶
erDiagram
Actor
CognitivePolicy
Epic
Evidence
Feature
Initiative
IntelInsight
Kaizen
Memory
Narrative
Research
Retrospective
Spike
StatusReport
Theme
WorkflowEvent
CognitivePolicy }o..|| Memory : "memory (inferred)"
Initiative }o..|| Theme : "theme_ref (inferred)"
Kaizen }o..|| Actor : "actor (inferred)"
Narrative }o..|| Actor : "actor (inferred)"
Retrospective }o..|| Actor : "actor (inferred)"
Spike }o..}o Research : "research_refs (inferred)"
StatusReport }o..}o Evidence : "evidence_refs (inferred)"
StatusReport }o..|| IntelInsight : "insight (inferred)"
WorkflowEvent }o..|| Actor : "actor (inferred)"
WorkflowEvent }o..|| Epic : "epic_ref (inferred)"
WorkflowEvent }o..|| Feature : "feature_ref (inferred)"
tenant (3 edges)¶
erDiagram
Role
Tenant
TenantMembership
Workspace
WorkspaceScopeGrant
TenantMembership }o..|| Role : "role (inferred)"
TenantMembership }o..|| Tenant : "tenant_slug (inferred)"
WorkspaceScopeGrant }o..|| Workspace : "workspace_id (inferred)"
testkit (2 edges)¶
erDiagram
Evidence
TestGuide
TestRun
TestRun }o..}o Evidence : "evidence (inferred)"
TestRun }o..|| TestGuide : "guide_ref (inferred)"
Groups with fewer than 2 edges (listed, not drawn): agentskills, kinddef, lesson.
Declared edges (x-dna-ref)¶
Enforced at write time. This table is the part of the graph the system will not let you break.
| From | Field | To | Cardinality | Cross-group |
|---|---|---|---|---|
Epic |
features |
Feature |
many | |
Feature |
epic |
Epic |
one | |
Feature |
stories |
Story |
many | |
Membership |
scope_ref (poly) |
Organization |
one | |
Membership |
scope_ref (poly) |
Project |
one | |
Plan |
epic |
Epic |
one | |
Plan |
spec_ref |
Spec |
one | |
Project |
org_ref |
Organization |
one | |
Project |
repo_refs |
Repo |
many | |
Spec |
epic |
Epic |
one | |
Spec |
supersedes |
Spec |
one | |
Story |
dependencies |
Story |
many | |
Story |
feature |
Feature |
one | |
Story |
spec_refs |
Spec |
many | |
Task |
story_ref |
Story |
one |
Composition edges (dep_filters only)¶
Declared for prompt composition, never validated against stored
data. Each row is a candidate for an x-dna-ref promotion.
| From | Field | To | Cardinality | Cross-group |
|---|---|---|---|---|
ADR |
covers_features |
Feature |
many | |
ADR |
superseded_by |
ADR |
one | |
ADR |
supersedes |
ADR |
many | |
Agent |
actors |
Actor |
one | |
Agent |
guardrails |
Guardrail |
many | yes |
Agent |
skills |
Skill |
many | yes |
Agent |
soul |
Soul |
one | yes |
Agent |
tools |
Tool |
many | |
AgentSession |
participants |
Actor |
many | yes |
Bug |
fix_adr |
ADR |
one | |
Bug |
related_feature |
Feature |
one | |
Bug |
related_story |
Story |
one | |
EvalSuite |
cases |
EvalCase |
many | |
Feature |
owner |
Actor |
one | yes |
Feature |
use_cases |
UseCase |
many | yes |
Initiative |
epics |
Epic |
many | |
Initiative |
owner |
Actor |
one | yes |
Issue |
owner |
Actor |
one | yes |
Issue |
related_feature |
Feature |
one | |
Kaizen |
issue |
Issue |
one | |
Narrative |
covers_epics |
Epic |
many | |
Narrative |
covers_features |
Feature |
many | |
Narrative |
covers_stories |
Story |
many | |
Postmortem |
related_features |
Feature |
many | |
Postmortem |
related_stories |
Story |
many | |
Retrospective |
covers_epics |
Epic |
many | |
Retrospective |
covers_features |
Feature |
many | |
Retrospective |
covers_session |
AgentSession |
one | |
Retrospective |
covers_stories |
Story |
many | |
RiskRegister |
owner |
Actor |
one | yes |
RiskRegister |
related_epics |
Epic |
many | |
RiskRegister |
related_features |
Feature |
many | |
Roadmap |
epics |
Epic |
one | |
SafetyPolicy |
recognizers |
Recognizer |
many | yes |
Spike |
feature |
Feature |
one | |
Spike |
follow_up_adr |
ADR |
one | |
Spike |
follow_up_spec |
Spec |
one | |
Spike |
follow_up_story |
Story |
one | |
Spike |
references |
Reference |
many | |
Spike |
related_spikes |
Spike |
many | |
Story |
owner |
Actor |
one | yes |
Task |
owner |
Actor |
one | yes |
UseCase |
agents |
Agent |
many | |
UseCase |
guardrails |
Guardrail |
many | yes |
UseCase |
primary_actor |
Actor |
one | |
UseCase |
skills |
Skill |
many | yes |
UseCase |
soul |
Soul |
one | yes |
UseCase |
supporting_actors |
Actor |
many | |
UseCase |
tools |
Tool |
many | |
WorkflowEvent |
parent_ref (poly) |
AgentSession |
one | |
WorkflowEvent |
parent_ref (poly) |
Epic |
one | |
WorkflowEvent |
parent_ref (poly) |
Feature |
one | |
WorkflowEvent |
parent_ref (poly) |
Narrative |
one | |
WorkflowEvent |
parent_ref (poly) |
Plan |
one | |
WorkflowEvent |
parent_ref (poly) |
Roadmap |
one | |
WorkflowEvent |
parent_ref (poly) |
Spec |
one | |
WorkflowEvent |
parent_ref (poly) |
Story |
one | |
WorkflowEvent |
ref (poly) |
AgentSession |
one | |
WorkflowEvent |
ref (poly) |
Epic |
one | |
WorkflowEvent |
ref (poly) |
Feature |
one | |
WorkflowEvent |
ref (poly) |
Narrative |
one | |
WorkflowEvent |
ref (poly) |
Plan |
one | |
WorkflowEvent |
ref (poly) |
Roadmap |
one | |
WorkflowEvent |
ref (poly) |
Spec |
one | |
WorkflowEvent |
ref (poly) |
Story |
one | |
WorkflowEvent |
transitioned_from |
WorkflowEvent |
one |
Inferred edges (name convention)¶
Not declared anywhere. Each row is this generator matching a field name against the Kind registry — useful, and fallible.
| From | Field | To | Cardinality | Cross-group |
|---|---|---|---|---|
Actor |
role |
Role |
one | yes |
Agent |
promptTemplate |
PromptTemplate |
one | yes |
AuditLog |
roles |
Role |
many | yes |
CognitivePolicy |
memory |
Memory |
one | yes |
EvalBaseline |
suite |
EvalSuite |
one | |
EvalRun |
suite |
EvalSuite |
one | |
Evidence |
suite |
EvalSuite |
one | yes |
EvidencePolicy |
events |
WorkflowEvent |
many | yes |
Initiative |
theme_ref |
Theme |
one | yes |
Kaizen |
actor |
Actor |
one | yes |
KindDefinition |
docs |
Doc |
one | yes |
Lesson |
skill |
Skill |
one | yes |
Narrative |
actor |
Actor |
one | yes |
Retrospective |
actor |
Actor |
one | yes |
Skill |
references |
Reference |
one | yes |
Spike |
research_refs |
Research |
many | yes |
StatusReport |
evidence_refs |
Evidence |
many | yes |
StatusReport |
insight |
IntelInsight |
one | yes |
TenantMembership |
role |
Role |
one | yes |
TenantMembership |
tenant_slug |
Tenant |
one | |
TestRun |
evidence |
Evidence |
many | yes |
TestRun |
guide_ref |
TestGuide |
one | |
UserRoleAssignment |
roles |
Role |
many | yes |
WorkflowEvent |
actor |
Actor |
one | yes |
WorkflowEvent |
epic_ref |
Epic |
one | |
WorkflowEvent |
feature_ref |
Feature |
one | |
WorkspaceScopeGrant |
workspace_id |
Workspace |
one |
What this model cannot express¶
A MER that implies completeness is worse than none. These are the known gaps, generated alongside everything else so they cannot be quietly dropped.
Known-undeclarable references¶
Real edges that x-dna-ref deliberately does NOT declare. It resolves
targets by document name, and these are keyed by something else —
declaring them would produce false write-time violations on perfectly
valid data. This is the concrete backlog for a future x-dna-ref-key.
| Kind | Field | Really points at | Why undeclarable |
|---|---|---|---|
Comment |
target_ref |
any |
a composite Kind:name string — needs parsing, not a name lookup |
Membership |
role |
Role |
keyed by role_id, not the document name |
Organization |
plan_ref |
Tier |
keyed by tier_id (free/pro/enterprise), not the document name |
Project |
workspace_id |
Workspace |
keyed by the Workspace's opaque generated workspace_id, not its document name |
WorkspaceMembership |
role |
Role |
keyed by role_id (owner/admin/member/guest), not the document name |
WorkspaceMembership |
workspace_id |
Workspace |
same opaque workspace_id key |
Unresolved reference-shaped fields¶
Fields that clearly point at something the model cannot name. This shrinks when references get declared, not when the generator gets cleverer.
| Kind | Field | Why unresolved |
|---|---|---|
AuditLog |
request_id |
reference-shaped, but request matches no registered Kind |
Engram |
affect_evidence_refs |
reference-shaped, but affect_evidence matches no registered Kind |
Engram |
source_refs |
reference-shaped, but source matches no registered Kind |
Evidence |
document_ref |
reference-shaped, but document matches no registered Kind |
Feature |
sprint_ref |
reference-shaped, but sprint matches no registered Kind |
IntelInsight |
source_ref |
reference-shaped, but source matches no registered Kind |
LayerPolicy |
layer_id |
reference-shaped, but layer matches no registered Kind |
ModelProfile |
model_id |
reference-shaped, but model matches no registered Kind |
PlanBinding |
account_id |
reference-shaped, but account matches no registered Kind |
PlanBinding |
stripe_customer_id |
reference-shaped, but stripe_customer matches no registered Kind |
PlanBinding |
stripe_subscription_id |
reference-shaped, but stripe_subscription matches no registered Kind |
PlanBinding |
tier_id |
reference-shaped, but tier matches no registered Kind |
PricingPlan |
tier_id |
reference-shaped, but tier matches no registered Kind |
Project |
intel_source_refs |
reference-shaped, but intel_source matches no registered Kind |
Research |
scope_ref |
reference-shaped, but scope matches no registered Kind |
SourceArtifact |
derived_refs |
reference-shaped, but derived matches no registered Kind |
Story |
sprint_ref |
reference-shaped, but sprint matches no registered Kind |
TenantMembership |
user_id |
reference-shaped, but user matches no registered Kind |
UserProfile |
user_id |
reference-shaped, but user matches no registered Kind |
UserRoleAssignment |
user_id |
reference-shaped, but user matches no registered Kind |
Workspace |
account_id |
reference-shaped, but account matches no registered Kind |
Workspace |
plan_ref |
reference-shaped, but plan matches no registered Kind |
WorkspaceMembership |
identity_oid |
reference-shaped, but identity matches no registered Kind |
Suppressed name matches¶
The name-convention pass matched these and each is wrong. Listed rather than silently dropped, so the suppression is auditable.
| Kind | Field | Why the match is wrong |
|---|---|---|
AgentSession |
tool |
provenance enum of the AI coding tool that produced the session (claude-code | cursor | cline | …), not a Tool document |
AuditLog |
actor |
the request identity string from claims (email/sub, or 'dev-user'), not a reference to an Actor document |
Copilot |
tenant |
inbound-tenant handling mode for the emitted serving layer, not a reference to a Tenant document |
Memory |
namespace |
MIF's hierarchical memory scope path (_semantic/decisions, §10) — a string axis inside the document, not the KindNamespace Kind, whose alias tenant-kind-namespace merely ends in the same token |
Organization |
plan_ref |
the DNA Cloud Tier this org is on, not the SDLC Plan Kind |
RemoteAgent |
skills |
the A2A Card's own skills[] (id/name/description/tags/examples) — structured self-description of what the remote agent can do, not a reference to the Skill Kind (agentskills), which merely shares the singular of the field name |
Tenant |
plan |
billing/feature tier (a Tier tier_id), not the SDLC Plan Kind |
Workspace |
plan_ref |
DEPRECATED and never read — billing is per ACCOUNT (workspace → account_id → AccountPlan); also not the SDLC Plan Kind |
Kinds with no reference edge (22)¶
Standalone documents — configuration, composition-plane behaviour, or record Kinds whose links are simply not modelled yet.
AgentDefinition, Automation, Canvas, Changelog, Comment, Copilot, Engram, Genome, Hook, HtmlArtifact, IntelSource, KindNamespace, LayerPolicy, MCPFederation, ModelProfile, PlanBinding, PricingPlan, RemoteAgent, Setting, SourceArtifact, UserProfile, WorkspaceMembership
Physical model — the real tables¶
This diagram carries little information, by design
7 tables on Postgres (4 on SQLite) and
0 foreign keys. They are a generic document store:
documents holds every Kind, of every type, as JSON in a
content column keyed by (scope, kind, name, tenant). Adding a
Kind adds rows, never a table — so the physical diagram cannot
show you the domain. The logical model above is where the domain
lives. This section exists to be accurate, not to look deep.
Postgres¶
erDiagram
dna_bundle_entries {
TEXT scope PK
TEXT kind PK
TEXT api_version PK
TEXT name PK
TEXT entry_path PK
TEXT content
TEXT updated_at
TEXT tenant PK
BLOB content_binary
}
dna_documents {
TEXT scope PK
TEXT kind PK
TEXT api_version PK
TEXT name PK
TEXT content
INTEGER version
TEXT updated_at
TEXT tenant PK
}
dna_layer_documents {
TEXT scope PK
TEXT layer_id PK
TEXT layer_value PK
TEXT kind PK
TEXT name PK
TEXT content
TEXT updated_at
}
dna_outbox {
BIGINT id PK
DATETIME occurred_at
TEXT scope
TEXT tenant
TEXT kind
TEXT name
TEXT op
INTEGER doc_version
TEXT actor
TEXT cause
}
dna_quota_counters {
DATE day PK
TEXT tenant PK
TEXT tier PK
BIGINT calls
}
dna_versions {
INTEGER id PK
TEXT scope
TEXT kind
TEXT api_version
TEXT name
TEXT content
INTEGER version
BOOLEAN is_draft
TEXT author
TEXT created_at
TEXT tenant
TEXT semver
}
dna_versions_seq {
TEXT scope PK
TEXT tenant PK
BIGINT last_id
DATETIME last_at
}
No lines connect these boxes because there are no foreign keys to
draw. The join key is (scope, kind, name, tenant), applied in
application code.
Dialect differences¶
The dialects are genuinely disjoint — Postgres tables carry a dna_
prefix, SQLite's do not, and Postgres has tables SQLite lacks.
| Postgres | SQLite |
|---|---|
dna_bundle_entries |
bundle_entries |
dna_documents |
documents |
dna_layer_documents |
layer_documents |
dna_outbox |
— |
dna_quota_counters |
— |
dna_versions |
versions |
dna_versions_seq |
— |
Columns¶
dna_bundle_entries¶
| Column | Type | Key | Nullable |
|---|---|---|---|
scope |
TEXT |
PK | |
kind |
TEXT |
PK | |
api_version |
TEXT |
PK | |
name |
TEXT |
PK | |
entry_path |
TEXT |
PK | |
content |
TEXT |
||
updated_at |
TEXT |
||
tenant |
TEXT |
PK | |
content_binary |
BLOB |
yes |
dna_documents¶
| Column | Type | Key | Nullable |
|---|---|---|---|
scope |
TEXT |
PK | |
kind |
TEXT |
PK | |
api_version |
TEXT |
PK | |
name |
TEXT |
PK | |
content |
TEXT |
||
version |
INTEGER |
||
updated_at |
TEXT |
||
tenant |
TEXT |
PK |
dna_layer_documents¶
| Column | Type | Key | Nullable |
|---|---|---|---|
scope |
TEXT |
PK | |
layer_id |
TEXT |
PK | |
layer_value |
TEXT |
PK | |
kind |
TEXT |
PK | |
name |
TEXT |
PK | |
content |
TEXT |
||
updated_at |
TEXT |
dna_outbox¶
| Column | Type | Key | Nullable |
|---|---|---|---|
id |
BIGINT |
PK | |
occurred_at |
DATETIME |
||
scope |
TEXT |
||
tenant |
TEXT |
||
kind |
TEXT |
||
name |
TEXT |
||
op |
TEXT |
||
doc_version |
INTEGER |
||
actor |
TEXT |
yes | |
cause |
TEXT |
yes |
dna_quota_counters¶
| Column | Type | Key | Nullable |
|---|---|---|---|
day |
DATE |
PK | |
tenant |
TEXT |
PK | |
tier |
TEXT |
PK | |
calls |
BIGINT |
dna_versions¶
| Column | Type | Key | Nullable |
|---|---|---|---|
id |
INTEGER |
PK | |
scope |
TEXT |
||
kind |
TEXT |
||
api_version |
TEXT |
||
name |
TEXT |
||
content |
TEXT |
||
version |
INTEGER |
||
is_draft |
BOOLEAN |
||
author |
TEXT |
yes | |
created_at |
TEXT |
||
tenant |
TEXT |
||
semver |
TEXT |
yes |
dna_versions_seq¶
| Column | Type | Key | Nullable |
|---|---|---|---|
scope |
TEXT |
PK | |
tenant |
TEXT |
PK | |
last_id |
BIGINT |
||
last_at |
DATETIME |