Initial curated itworx-knowledge-hub source from 3b1751d0d9dee551aa6994eee0093704dc334817
This commit is contained in:
commit
ad8ad252a9
825 files changed
+124216
No files matched your search
@@ -0,0 +1,256 @@
|
||||
# Database schema
|
||||
|
||||
This document defines the intended relational shape. EF Core migrations are the
|
||||
executable source once implemented. Names may be refined in M0/M1 through an ADR, but
|
||||
constraints and invariants must remain.
|
||||
|
||||
## Conventions
|
||||
|
||||
- PostgreSQL `uuid` primary keys generated by the application or database.
|
||||
- `timestamptz` for instants.
|
||||
- UTC application semantics.
|
||||
- lowercase snake_case database names.
|
||||
- explicit foreign keys and delete behavior.
|
||||
- `citext` or normalized columns for case-insensitive unique values.
|
||||
- `jsonb` only for versioned, non-core metadata and import diagnostics.
|
||||
- integer/bigint monotonic revision numbers where scoped.
|
||||
- byte/string concurrency token exposed as ETag.
|
||||
- no database credentials or secrets in data migrations.
|
||||
|
||||
## Identity and workspace
|
||||
|
||||
### installation
|
||||
|
||||
- `id` singleton key
|
||||
- `instance_id` uuid unique
|
||||
- `product_version`
|
||||
- `schema_version`
|
||||
- `primary_locale`
|
||||
- `time_zone`
|
||||
- `setup_completed_at`
|
||||
- timestamps / concurrency version
|
||||
|
||||
### users
|
||||
|
||||
Use ASP.NET Core Identity-compatible tables with application extensions:
|
||||
|
||||
- display name
|
||||
- enabled state
|
||||
- last login
|
||||
- security stamp
|
||||
- created/updated timestamps
|
||||
|
||||
### workspaces
|
||||
|
||||
- `id`
|
||||
- `name`
|
||||
- normalized `slug`
|
||||
- settings version
|
||||
- timestamps
|
||||
- archived timestamp
|
||||
|
||||
Unique: normalized slug.
|
||||
|
||||
### workspace_memberships
|
||||
|
||||
- workspace/user composite uniqueness
|
||||
- role
|
||||
- timestamps
|
||||
|
||||
Constraint: valid role enum. Application invariant: final admin cannot be removed.
|
||||
|
||||
## Knowledge tables
|
||||
|
||||
### pages
|
||||
|
||||
Important columns:
|
||||
|
||||
```text
|
||||
id uuid primary key
|
||||
workspace_id uuid not null
|
||||
parent_page_id uuid null
|
||||
sort_key text not null
|
||||
title varchar(300) not null
|
||||
normalized_title varchar(300) not null
|
||||
slug varchar(320) not null
|
||||
markdown text not null
|
||||
document_type smallint not null
|
||||
document_status smallint not null
|
||||
current_revision bigint not null
|
||||
content_hash char(64) not null
|
||||
concurrency_version bigint not null
|
||||
created_by / updated_by uuid
|
||||
created_at / updated_at / published_at timestamptz
|
||||
trashed_at / purge_after timestamptz null
|
||||
search_vector tsvector generated or maintained
|
||||
```
|
||||
|
||||
Indexes:
|
||||
|
||||
- `(workspace_id, parent_page_id, sort_key, id)`
|
||||
- `(workspace_id, slug)`
|
||||
- `(workspace_id, updated_at desc, id)`
|
||||
- partial active-page indexes where `trashed_at is null`
|
||||
- GIN `search_vector`
|
||||
- GIN/GiST trigram on normalized title
|
||||
- optional path/ancestor closure only if measured need justifies it
|
||||
|
||||
Cycle prevention is primarily application-controlled and integration-tested. A recursive
|
||||
query validates moves transactionally.
|
||||
|
||||
### page_revisions
|
||||
|
||||
Unique `(page_id, revision_number)`. Store immutable snapshots and content hash.
|
||||
|
||||
Indexes:
|
||||
|
||||
- page/revision descending
|
||||
- workspace/created timestamp
|
||||
- author/time where audit UI needs it
|
||||
|
||||
No cascade delete during ordinary content lifecycle.
|
||||
|
||||
### drafts
|
||||
|
||||
Unique `(workspace_id, user_id, draft_key)`. Draft content is private to the author.
|
||||
|
||||
### page_links
|
||||
|
||||
Unique identity includes source page, occurrence key and source revision. Index target
|
||||
page for backlinks and unresolved text for maintenance.
|
||||
|
||||
### page_relations
|
||||
|
||||
Unique `(source_page_id, target_page_id, relation_type)` unless multiple labels are
|
||||
explicitly supported.
|
||||
|
||||
### tags / page_tags
|
||||
|
||||
- normalized tag unique per workspace
|
||||
- composite join primary key
|
||||
- indexes for tag-filter search
|
||||
|
||||
### favorites / recent_visits
|
||||
|
||||
Composite user/content uniqueness. Recent visits use upserted last-view time and bounded
|
||||
retention.
|
||||
|
||||
## Attachments
|
||||
|
||||
### attachment_blobs
|
||||
|
||||
Primary key is 64-character lowercase SHA-256.
|
||||
|
||||
Columns include:
|
||||
|
||||
- length
|
||||
- detected media type
|
||||
- storage/preview/integrity states
|
||||
- created/verified timestamps
|
||||
- reference count cache only if transactionally maintained
|
||||
|
||||
### attachment_references
|
||||
|
||||
Stable logical ID, workspace, blob hash, safe original filename and descriptive metadata.
|
||||
|
||||
### attachment_usages
|
||||
|
||||
Polymorphic ownership must not use an unconstrained arbitrary string alone. Prefer
|
||||
separate nullable constrained columns or typed join tables for page/project update usage.
|
||||
The selected design requires an ADR.
|
||||
|
||||
Indexes support owner lookup and orphan discovery.
|
||||
|
||||
## Projects
|
||||
|
||||
### projects
|
||||
|
||||
Unique normalized project slug per workspace. Index lifecycle status and last update.
|
||||
|
||||
### project_documents
|
||||
|
||||
Unique `(project_id, page_id, role)`.
|
||||
|
||||
### project_updates
|
||||
|
||||
Ordered by `(occurred_at desc, id desc)`. Immutable content with correction/supersession
|
||||
links.
|
||||
|
||||
### project_milestones
|
||||
|
||||
Unique name or sequence per project; stable sort key.
|
||||
|
||||
### technology_tags / project_technology_tags
|
||||
|
||||
Normalized unique technology name per workspace.
|
||||
|
||||
## Decisions and runbooks
|
||||
|
||||
### decision_records
|
||||
|
||||
- unique page profile
|
||||
- unique accepted decision number per project
|
||||
- self-referencing supersession constraints
|
||||
- indexes by project/status/date
|
||||
|
||||
### runbook_profiles
|
||||
|
||||
- unique page profile
|
||||
- risk/validation metadata
|
||||
- review/validation indexes
|
||||
|
||||
## Imports
|
||||
|
||||
### import_jobs
|
||||
|
||||
Unique source fingerprint plus invocation identity does not automatically prevent a new
|
||||
deliberate import, but idempotency keys prevent duplicate execution.
|
||||
|
||||
### import_items
|
||||
|
||||
Unique `(import_job_id, source_identity)`. Index target identities and status.
|
||||
|
||||
### import_provenance
|
||||
|
||||
Links imported target rows to job/item. This table is the authoritative rollback scope.
|
||||
|
||||
## Audit, jobs and outbox
|
||||
|
||||
### audit_events
|
||||
|
||||
Append-only, indexed by workspace/time, actor/time, target/time and correlation ID.
|
||||
Partitioning is deferred until measured volume warrants it.
|
||||
|
||||
### background_jobs
|
||||
|
||||
Durable state, lease owner/expiry, attempt count, schedule, progress and safe diagnostics.
|
||||
|
||||
### outbox_messages
|
||||
|
||||
Index unprocessed `(available_at, id)`. Retention after successful dispatch is
|
||||
configurable.
|
||||
|
||||
## Search implementation
|
||||
|
||||
Use the PostgreSQL `simple` text-search configuration initially because documents mix
|
||||
Dutch, English, code, commands and product names. Maintain normalized searchable text
|
||||
from:
|
||||
|
||||
- title;
|
||||
- stripped Markdown text;
|
||||
- tags;
|
||||
- selected structured metadata.
|
||||
|
||||
Use trigram matching for titles/slugs/tags and explicit ranking weights. Permission
|
||||
filters must be part of the query, not a post-filter after result selection.
|
||||
|
||||
## Migration requirements
|
||||
|
||||
Every migration must:
|
||||
|
||||
- be deterministic;
|
||||
- be tested from the previous released schema;
|
||||
- avoid silent data truncation;
|
||||
- include data backfill verification where needed;
|
||||
- document locks/expected duration for large tables;
|
||||
- have a tested application rollback strategy even when SQL downgrade is unsafe.
|
||||
Reference in new issue
Block a user