@gnolith/taproot 0.1.0-rc.0
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.
- package/CHANGELOG.md +14 -0
- package/COMPATIBILITY.md +42 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/SECURITY.md +19 -0
- package/SUPPORT.md +11 -0
- package/dist/canonical.d.ts +16 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +519 -0
- package/dist/canonical.js.map +1 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +42 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/iri.d.ts +3 -0
- package/dist/iri.d.ts.map +1 -0
- package/dist/iri.js +8 -0
- package/dist/iri.js.map +1 -0
- package/dist/rdf.d.ts +6 -0
- package/dist/rdf.d.ts.map +1 -0
- package/dist/rdf.js +292 -0
- package/dist/rdf.js.map +1 -0
- package/dist/repository.d.ts +94 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +1499 -0
- package/dist/repository.js.map +1 -0
- package/dist/schema.d.ts +19 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +390 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +299 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/docs/api.md +47 -0
- package/docs/architecture.md +30 -0
- package/docs/completion-audit.md +31 -0
- package/docs/operations.md +47 -0
- package/docs/product-scope.md +20 -0
- package/docs/release-policy.md +16 -0
- package/docs/testing.md +21 -0
- package/docs/threat-model.md +40 -0
- package/examples/codex-site/.openai/hosting.json +3 -0
- package/examples/codex-site/README.md +13 -0
- package/examples/codex-site/demo.ts +152 -0
- package/migrations/0001_taproot.sql +64 -0
- package/migrations/0002_audit_operations.sql +48 -0
- package/package.json +89 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
- Complete Wikibase Item/Property JSON model and validated editing API.
|
|
6
|
+
- Atomic current entities, immutable revisions, terms, RDF, and ownership.
|
|
7
|
+
- Structured attribution, tags, request correlation, audit events, and
|
|
8
|
+
SHA-256 parent chains.
|
|
9
|
+
- Lifecycle history, redirect resolution/cycle prevention, cursor reads,
|
|
10
|
+
multi-command edits, bounded bulk import/upsert, and NDJSON export.
|
|
11
|
+
- Schema/RDF migration, integrity inspection, audit verification, and repair.
|
|
12
|
+
- Wikibase-compatible truthy/full RDF mapping version 2 and shared-value safety.
|
|
13
|
+
- Host validators, attribution enforcement, observations, deterministic test
|
|
14
|
+
injection, Workerd/D1 tests, Node 22/24 CI, and pack validation.
|
package/COMPATIBILITY.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Wikibase compatibility target
|
|
2
|
+
|
|
3
|
+
Taproot targets the canonical entity shapes and RDF vocabulary paths used by
|
|
4
|
+
the Wikibase API/RDF model, with site-owned entity/property namespaces. The
|
|
5
|
+
fixtures under `test/fixtures` are the named interoperability baseline.
|
|
6
|
+
|
|
7
|
+
Intentional differences:
|
|
8
|
+
|
|
9
|
+
- Taproot is a library over D1, not a MediaWiki or Wikibase HTTP server.
|
|
10
|
+
- Local Q/P IDs, base IRI, revision numbers, statement IDs, and reference
|
|
11
|
+
hashes belong to the site. Imported values are preserved; Taproot does not
|
|
12
|
+
call Wikidata to resolve or rewrite them.
|
|
13
|
+
- Sitelinks round-trip in canonical JSON but are not wiki-page storage and do
|
|
14
|
+
not emit MediaWiki page metadata.
|
|
15
|
+
- Redirect and soft-delete state live beside canonical JSON and project only
|
|
16
|
+
lifecycle RDF; deleted content remains available in immutable revisions.
|
|
17
|
+
- Search is a deterministic D1 term projection using case-insensitive
|
|
18
|
+
substring matching. FTS5 is not required.
|
|
19
|
+
- Taproot stores attribution claims but does not authenticate them. Identity
|
|
20
|
+
verification, authorization, and agent/MCP transport remain host concerns.
|
|
21
|
+
- The compatibility target is Wikibase core Items and Properties. Lexemes,
|
|
22
|
+
Forms, Senses, EntitySchemas, MediaInfo, MediaWiki page metadata, and
|
|
23
|
+
normalized external-ID formatter URLs are not claimed as supported entity
|
|
24
|
+
surfaces.
|
|
25
|
+
- Item/Property statements can nevertheless store and project the standard
|
|
26
|
+
`wikibase-lexeme`, `wikibase-form`, `wikibase-sense`, and `entity-schema`
|
|
27
|
+
link datatypes without claiming storage for those target entity documents.
|
|
28
|
+
- Math, musical notation, geo-shape, and tabular-data values round-trip and
|
|
29
|
+
project with Wikibase property types. Geo-shape/tabular-data values use
|
|
30
|
+
Commons data IRIs; deployments remain responsible for those resources.
|
|
31
|
+
- Taproot adds a site-owned mapping-version triple and retains
|
|
32
|
+
`schema:isBasedOn` beside standard `prov:wasDerivedFrom` for backward
|
|
33
|
+
compatibility. These additive triples do not change Wikibase query paths.
|
|
34
|
+
- Shared full-value/reference RDF nodes are reference-owned internally so
|
|
35
|
+
incremental edits never remove a quad still used by another entity. The
|
|
36
|
+
ownership table is projection bookkeeping, not an authoritative statement
|
|
37
|
+
store.
|
|
38
|
+
|
|
39
|
+
Interoperability means canonical Item/Property JSON round-trip and equivalent
|
|
40
|
+
Wikibase query paths (`wdt`, `p`, `ps`, `psv`, `pq`, `pqv`, `pr`, `prv`,
|
|
41
|
+
`wdno`) under a site-owned base IRI. It does not mean Taproot implements the
|
|
42
|
+
MediaWiki/Wikibase HTTP APIs or every extension entity type.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gnolith contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Taproot
|
|
2
|
+
|
|
3
|
+
**The D1-native, Wikibase-compatible knowledge layer for Gnolith.**
|
|
4
|
+
|
|
5
|
+
Taproot gives a Codex Site one authoritative Wikibase-shaped Item/Property
|
|
6
|
+
document, tamper-evident revision and attribution history, typed and batched
|
|
7
|
+
editing commands, term search, repairable projections, and a deterministic RDF projection stored and queried by
|
|
8
|
+
[`@gnolith/diamond`](https://github.com/gnolith/diamond).
|
|
9
|
+
|
|
10
|
+
> One canonical entity document, one deterministic RDF projection, one atomic
|
|
11
|
+
> revision boundary.
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Version `0.1.0` is the first public release. Taproot supports Node 22 and 24 and
|
|
16
|
+
depends on the registry release of Diamond that exposes transaction-composable
|
|
17
|
+
quad patches.
|
|
18
|
+
|
|
19
|
+
## What it owns
|
|
20
|
+
|
|
21
|
+
- Items and Properties with Wikibase-style canonical JSON.
|
|
22
|
+
- Labels, descriptions, aliases, sitelinks, statements, qualifiers,
|
|
23
|
+
references, ranks, and all three snak types.
|
|
24
|
+
- Item, Property, Lexeme, Form, Sense, and EntitySchema links; string,
|
|
25
|
+
external ID, URL, Commons media, monolingual text, time,
|
|
26
|
+
quantity, coordinate, math, musical notation, geo-shape, and tabular-data
|
|
27
|
+
datatypes.
|
|
28
|
+
- Atomic Q/P ID allocation, current documents, immutable revisions, lifecycle
|
|
29
|
+
history, structured human/agent/import/system attribution, tags, request
|
|
30
|
+
correlation, audit events, and the term-search projection in D1.
|
|
31
|
+
- A complete deterministic Wikibase-shaped RDF closure with truthy/best-rank,
|
|
32
|
+
special-value, and full-value behavior.
|
|
33
|
+
- Cursor reads, bounded import/upsert and NDJSON export, multi-command edits,
|
|
34
|
+
redirect resolution, integrity verification, deterministic repair, schema/RDF
|
|
35
|
+
migrations, validation policies, and write observations.
|
|
36
|
+
|
|
37
|
+
It does not own authentication, MCP, agents, tasks, UI, wiki articles, media
|
|
38
|
+
bytes, or arbitrary SPARQL Update. Canonical entity JSON is authoritative;
|
|
39
|
+
there is no relational statement store.
|
|
40
|
+
|
|
41
|
+
## Setup
|
|
42
|
+
|
|
43
|
+
Taproot requires Diamond's transaction-composable quad-patch API. Initialize a
|
|
44
|
+
D1 binding once; the programmatic initializer creates both Diamond and Taproot
|
|
45
|
+
tables idempotently:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { TaprootRepository, initializeTaproot } from '@gnolith/taproot';
|
|
49
|
+
|
|
50
|
+
await initializeTaproot(env.DB);
|
|
51
|
+
const knowledge = new TaprootRepository(env.DB, {
|
|
52
|
+
baseIri: 'https://knowledge.example',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const property = await knowledge.createProperty({
|
|
56
|
+
datatype: 'string',
|
|
57
|
+
labels: { en: { language: 'en', value: 'occupation' } },
|
|
58
|
+
});
|
|
59
|
+
const item = await knowledge.createItem({
|
|
60
|
+
labels: { en: { language: 'en', value: 'Ada Lovelace' } },
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For migration-driven deployments, apply Diamond's migrations and the numbered
|
|
65
|
+
Taproot SQL files, then call `initializeTaproot()`. The initializer performs
|
|
66
|
+
the application-level SHA-256 backfill that SQLite SQL alone cannot perform,
|
|
67
|
+
reprojects older RDF mapping versions, installs immutability triggers, and is
|
|
68
|
+
safe to run on every startup/deploy.
|
|
69
|
+
|
|
70
|
+
## Editing
|
|
71
|
+
|
|
72
|
+
Every mutation after creation requires `expectedRevision`. Taproot loads the
|
|
73
|
+
current document, validates the typed change and all referenced Property
|
|
74
|
+
datatypes, serializes canonical JSON, rebuilds the complete old/new RDF
|
|
75
|
+
closures, and batches the current row, immutable revision, search terms, and
|
|
76
|
+
Diamond patch together. A stale guard or any SQL/RDF failure rolls the whole
|
|
77
|
+
batch back.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const edited = await knowledge.setLabel(item.entityId, 'fr', 'Ada Lovelace', {
|
|
81
|
+
expectedRevision: item.newRevision,
|
|
82
|
+
attribution: {
|
|
83
|
+
id: 'agent:cataloguer',
|
|
84
|
+
kind: 'agent',
|
|
85
|
+
tool: 'gnolith-mcp',
|
|
86
|
+
},
|
|
87
|
+
editSummary: 'add French label',
|
|
88
|
+
tags: ['agent'],
|
|
89
|
+
requestId: 'mcp-request-123',
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The public API includes reads/search; create/import/replace; soft delete,
|
|
94
|
+
restore, and redirect; all term/sitelink commands; complete statement,
|
|
95
|
+
qualifier, reference, and rank commands; audit/history and integrity reads;
|
|
96
|
+
bulk workflows; and canonical JSON parse, validate, create, and export helpers. Top-level function forms are exported alongside
|
|
97
|
+
`TaprootRepository`.
|
|
98
|
+
|
|
99
|
+
Set `requireAttribution: true` to reject unattributed writes. `validators`
|
|
100
|
+
provide host policy checks without coupling Taproot to authentication, and
|
|
101
|
+
`observe` receives isolated success/error timing records for committed writes.
|
|
102
|
+
|
|
103
|
+
## SPARQL prefixes
|
|
104
|
+
|
|
105
|
+
`wikibasePrefixes(baseIri)` returns site-owned `wd:`, `wds:`, `wdv:`,
|
|
106
|
+
`wdref:`, `wdt:`, `p:`, `ps:`, `psv:`, `pq:`, `pqv:`, `pr:`, `prv:`, and
|
|
107
|
+
`wdno:` namespaces. Pass the D1 binding to Diamond's read-only SPARQL handler
|
|
108
|
+
to query them.
|
|
109
|
+
|
|
110
|
+
## Limits
|
|
111
|
+
|
|
112
|
+
Canonical entity JSON defaults to 1.8 MB, below D1's 2 MB bound-value limit.
|
|
113
|
+
Diamond enforces a 1.9 MB aggregate encoded quad-patch limit; Taproot reports
|
|
114
|
+
that as `QuadPatchTooLargeError`. Store PDFs, images, audio, OCR, transcripts,
|
|
115
|
+
and article bodies externally and represent them as knowledge Items.
|
|
116
|
+
|
|
117
|
+
Bulk imports default to create-only, can opt into `upsert`, are capped at 100
|
|
118
|
+
entities by default, and commit one entity atomically at a time. Multi-command
|
|
119
|
+
edits apply up to 100 commands in one revision. All list limits are capped at 500.
|
|
120
|
+
|
|
121
|
+
See the [Codex Site example](examples/codex-site/README.md),
|
|
122
|
+
[`COMPATIBILITY.md`](COMPATIBILITY.md), and the architecture, API, operations,
|
|
123
|
+
and release documents under `docs/`. Run `npm run check` for the complete local
|
|
124
|
+
release-quality gate.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Report vulnerabilities privately through GitHub Security Advisories. Do not
|
|
4
|
+
open a public issue for an undisclosed vulnerability.
|
|
5
|
+
|
|
6
|
+
The latest published minor line receives security fixes. Older pre-1.0 minor
|
|
7
|
+
lines are unsupported unless a security advisory explicitly says otherwise.
|
|
8
|
+
|
|
9
|
+
Include the affected API, a minimal D1/entity reproduction, impact on
|
|
10
|
+
canonical history or RDF query results, and whether untrusted JSON or SPARQL
|
|
11
|
+
input is required. Do not include production data or credentials.
|
|
12
|
+
|
|
13
|
+
Taproot records attribution claims but does not authenticate identities or
|
|
14
|
+
authorize writes. Hosts must keep mutation routes trusted. Canonical JSON,
|
|
15
|
+
revision/audit immutability, size limits, optimistic revision guards, and
|
|
16
|
+
read-only Diamond SPARQL are security boundaries; projection tables are not.
|
|
17
|
+
|
|
18
|
+
The threat model and host responsibilities are documented in
|
|
19
|
+
`docs/threat-model.md`.
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Support
|
|
2
|
+
|
|
3
|
+
Use GitHub Issues for reproducible defects and scoped feature requests. Include
|
|
4
|
+
the Taproot, Diamond, Node, Workerd/Wrangler, and schema versions; the smallest
|
|
5
|
+
canonical entity or command that reproduces the problem; and observed versus
|
|
6
|
+
expected behavior.
|
|
7
|
+
|
|
8
|
+
Only versions listed as supported in `SECURITY.md` receive security fixes.
|
|
9
|
+
There is no guaranteed response time or commercial support commitment.
|
|
10
|
+
Do not disclose vulnerabilities publicly; use GitHub private vulnerability
|
|
11
|
+
reporting instead.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type DataValueValue, type EntityId, type PropertyId, type Reference, type Snak, type Statement, type WikibaseEntity } from './types.js';
|
|
2
|
+
export declare const MAX_ENTITY_BYTES = 1800000;
|
|
3
|
+
export declare function parseEntityJson(json: string): WikibaseEntity;
|
|
4
|
+
export declare function validateEntity(value: unknown): asserts value is WikibaseEntity;
|
|
5
|
+
export declare function exportEntityJson(entity: WikibaseEntity, maxBytes?: number): string;
|
|
6
|
+
export declare function canonicalizeEntity(entity: WikibaseEntity): WikibaseEntity;
|
|
7
|
+
export declare function validateSnak(value: unknown): asserts value is Snak;
|
|
8
|
+
export declare function entityNumericId(id: EntityId): number;
|
|
9
|
+
export declare function cloneEntity(entity: WikibaseEntity): WikibaseEntity;
|
|
10
|
+
export declare function cloneDataValue(value: DataValueValue): DataValueValue;
|
|
11
|
+
export declare function createStatement(entityId: EntityId, mainsnak: Snak, options?: {
|
|
12
|
+
id?: string;
|
|
13
|
+
rank?: Statement['rank'];
|
|
14
|
+
}): Statement;
|
|
15
|
+
export declare function createReference(snaks: Record<PropertyId, Snak[]>, hash?: string): Reference;
|
|
16
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAOA,OAAO,EAGL,KAAK,cAAc,EAEnB,KAAK,QAAQ,EAIb,KAAK,UAAU,EAGf,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,SAAS,EAEd,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,gBAAgB,UAAY,CAAC;AAQ1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAW5D;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,KAAK,IAAI,cAAc,CAoDjC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,EACtB,QAAQ,SAAmB,GAC1B,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAyBzE;AA2MD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAkClE;AA0PD,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAElE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAEpE;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,IAAI,EACd,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;CAAO,GACtD,SAAS,CAWX;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,EACjC,IAAI,SAAyC,GAC5C,SAAS,CASX"}
|