Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ All notable changes to **basou** are recorded here. The project follows

### Added

- `@basou/core` now ships JSON Schema artifacts for the on-disk `.basou/`
document formats, generated from the canonical Zod schemas (so they cannot
drift from validation). One schema per document — `manifest`, `session`,
`event` (a `oneOf` over the event type), `task`, `approval`, `status`,
`task-index`, and `session-import` — each a draft 2020-12 document with a
stable `$id` (`https://basou.dev/schemas/0.1.0/<name>.schema.json`). They let
non-JavaScript / cross-language tooling and editors validate `.basou/` files
directly. Published under the package's `./schemas/*` export (e.g.
`@basou/core/schemas/session.schema.json`). Prefixed-id fields carry a faithful
ULID `pattern`; other refinement-only constraints are not expressible in JSON
Schema and are omitted. Regenerate with `pnpm --filter @basou/core
gen:schemas`; a drift-guard test fails CI if the committed files fall behind
the Zod source.
- `@basou/sdk` v0.2 — the package gains a runtime, read-only programmatic API
for reading a workspace's provenance (it was types-only before). It is a
thin, ergonomic, semver-stable facade over `@basou/core`'s readers, so
Expand Down
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"!**/node_modules",
"!**/coverage",
"!**/*.tsbuildinfo",
"!**/pnpm-lock.yaml"
"!**/pnpm-lock.yaml",
"!packages/core/schemas"
]
},
"assist": { "actions": { "source": { "organizeImports": "on" } } },
Expand Down
14 changes: 11 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"audit",
"provenance",
"git",
"claude-code"
"claude-code",
"json-schema"
],
"repository": {
"type": "git",
Expand All @@ -35,17 +36,20 @@
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"./schemas/*": "./schemas/*"
},
"files": [
"dist"
"dist",
"schemas"
],
"engines": {
"node": ">=20.10.0"
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"gen:schemas": "pnpm build && node scripts/gen-schemas.mjs",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
Expand All @@ -57,5 +61,9 @@
"ulid": "^3.0.2",
"yaml": "^2.9.0",
"zod": "^4.4.3"
},
"devDependencies": {
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1"
}
}
130 changes: 130 additions & 0 deletions packages/core/schemas/approval.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://basou.dev/schemas/0.1.0/approval.schema.json",
"title": "Basou Approval",
"description": "A `.basou/approvals/{pending,resolved}/<id>.yaml` approval record.",
"type": "object",
"properties": {
"schema_version": {
"type": "string",
"const": "0.1.0"
},
"id": {
"type": "string",
"pattern": "^appr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"description": "Basou appr id: `appr_` followed by a 26-character Crockford Base32 ULID."
},
"session_id": {
"type": "string",
"pattern": "^ses_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"description": "Basou ses id: `ses_` followed by a 26-character Crockford Base32 ULID."
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"status": {
"type": "string",
"enum": [
"pending",
"approved",
"rejected",
"expired"
]
},
"risk_level": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"critical"
]
},
"action": {
"type": "object",
"properties": {
"kind": {
"type": "string"
}
},
"required": [
"kind"
],
"additionalProperties": {}
},
"reason": {
"type": "string"
},
"expires_at": {
"default": null,
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"resolver": {
"default": null,
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"resolved_at": {
"default": null,
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"note": {
"default": null,
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"rejection_reason": {
"default": null,
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"schema_version",
"id",
"session_id",
"created_at",
"status",
"risk_level",
"action",
"reason"
]
}
Loading