@gregiteen/ssss-cli 0.7.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 +124 -0
- package/LICENSE +15 -0
- package/README.md +162 -0
- package/VERSION +1 -0
- package/conformance/README.md +72 -0
- package/conformance/fixtures.json +763 -0
- package/conformance/reference-bundle.ucw.json +135 -0
- package/docs/help/autolink.md +15 -0
- package/docs/help/bundle.md +47 -0
- package/docs/help/conformance.md +34 -0
- package/docs/help/export.md +20 -0
- package/docs/help/import.md +19 -0
- package/docs/help/overview.md +33 -0
- package/docs/help/portability.md +27 -0
- package/docs/help/provision.md +19 -0
- package/docs/help/provisioning.md +43 -0
- package/docs/help/roles.md +61 -0
- package/docs/help/runtime.md +78 -0
- package/docs/help/scaffold.md +47 -0
- package/docs/ssss-spec.md +1325 -0
- package/package.json +62 -0
- package/registry/core.json +225 -0
- package/registry/extensions/festech.json +134 -0
- package/scripts/audit-registry-field-usage.mjs +136 -0
- package/scripts/autolink.mjs +341 -0
- package/scripts/build-reference-bundle.mjs +169 -0
- package/scripts/cmd-export.mjs +72 -0
- package/scripts/cmd-help.mjs +60 -0
- package/scripts/cmd-import.mjs +71 -0
- package/scripts/cmd-inspect.mjs +78 -0
- package/scripts/cmd-new.mjs +262 -0
- package/scripts/cmd-provision.mjs +68 -0
- package/scripts/cmd-validate.mjs +43 -0
- package/scripts/conformance.mjs +408 -0
- package/scripts/lib/cli.mjs +92 -0
- package/scripts/release.sh +35 -0
- package/scripts/ssss.mjs +93 -0
- package/scripts/validate-skills.mjs +115 -0
- package/src/bundle.mjs +261 -0
- package/src/engine.mjs +452 -0
- package/src/frontmatter.mjs +109 -0
- package/src/registry.mjs +67 -0
- package/src/runtime.mjs +212 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest": {
|
|
3
|
+
"name": "Festival in a Box",
|
|
4
|
+
"description": "A complete music-festival operation as a tradeable SSSS bundle.",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"exported_at": "1970-01-01T00:00:00.000Z",
|
|
7
|
+
"ssss_core_version": "0.6",
|
|
8
|
+
"required_extensions": [
|
|
9
|
+
"festech"
|
|
10
|
+
],
|
|
11
|
+
"export_profile": "sale",
|
|
12
|
+
"primitive_inventory": {
|
|
13
|
+
"assistant": 1,
|
|
14
|
+
"domain": 1,
|
|
15
|
+
"page": 1,
|
|
16
|
+
"security_role": 1,
|
|
17
|
+
"rule": 1,
|
|
18
|
+
"workflow": 1
|
|
19
|
+
},
|
|
20
|
+
"provisioning": [
|
|
21
|
+
{
|
|
22
|
+
"id": "ws",
|
|
23
|
+
"label": "Create the workspace",
|
|
24
|
+
"system": "workspace",
|
|
25
|
+
"mode": "generate",
|
|
26
|
+
"required": true
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "dom",
|
|
30
|
+
"label": "Bind the festival domain",
|
|
31
|
+
"system": "domains",
|
|
32
|
+
"mode": "provision",
|
|
33
|
+
"required": true,
|
|
34
|
+
"notes": "owns_domain — buyer supplies their own domain."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "mail",
|
|
38
|
+
"label": "Provision a support mailbox",
|
|
39
|
+
"system": "email",
|
|
40
|
+
"mode": "provision",
|
|
41
|
+
"required": false
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"parameters": [
|
|
45
|
+
{
|
|
46
|
+
"key": "business_name",
|
|
47
|
+
"label": "Festival name",
|
|
48
|
+
"type": "string",
|
|
49
|
+
"scope": "workspace",
|
|
50
|
+
"source": "user",
|
|
51
|
+
"required": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"key": "domain",
|
|
55
|
+
"label": "Domain to bind",
|
|
56
|
+
"type": "string",
|
|
57
|
+
"scope": "workspace",
|
|
58
|
+
"source": "user",
|
|
59
|
+
"required": true,
|
|
60
|
+
"description": "Satisfies the resource_bound domain requirement (owns_domain)."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"key": "support_mailbox",
|
|
64
|
+
"label": "Support mailbox",
|
|
65
|
+
"type": "string",
|
|
66
|
+
"scope": "workspace",
|
|
67
|
+
"source": "user",
|
|
68
|
+
"required": false
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"file_count": 14,
|
|
72
|
+
"provenance": {
|
|
73
|
+
"content_hash": "sha256:96380f618ee1e178331beca9507e1b3cd28a3d12cfa7f9898317f98da8295218",
|
|
74
|
+
"exporter": "@ssss/cli@0.7.0"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"files": [
|
|
78
|
+
{
|
|
79
|
+
"path": "assistants/concierge.md",
|
|
80
|
+
"content": "---\ntype: assistant\ntitle: Festival Concierge\ndescription: Assistant that answers attendee questions about the lineup and venue.\ntimestamp: 2026-07-02T00:00:00Z\nname: Festival Concierge\nslug: concierge\n---\nAnswer attendee questions about the lineup and venue."
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "assistants/index.md",
|
|
84
|
+
"content": "# Index — assistants\n\n- [Festival Concierge](./concierge.md)\n"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"path": "domains/festival.md",
|
|
88
|
+
"content": "---\ntype: domain\ntitle: Festival Domain Requirement\ndescription: Domain resource requirement that the buyer binds during provisioning.\ntimestamp: 2026-07-02T00:00:00Z\ndomain_name: REQUIREMENT\nregistrar: REQUIREMENT\nstatus: required\npayment_status: unbound\nx_portability: resource_bound\n---\nThis festival needs a domain. The buyer binds their own at provision (owns_domain)."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"path": "domains/index.md",
|
|
92
|
+
"content": "# Index — domains\n\n- [Festival Domain Requirement](./festival.md)\n"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"path": "pages/index.md",
|
|
96
|
+
"content": "# Index — pages\n\n- [Lineup](./lineup.md)\n"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"path": "pages/lineup.md",
|
|
100
|
+
"content": "---\ntype: page\ntitle: Lineup\ndescription: Public-facing festival lineup page.\ntimestamp: 2026-07-02T00:00:00Z\nslug: lineup\nname: Lineup\nsandbox_entry: lineup/index.html\n---\nThe festival lineup page."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"path": "roles/admin/ROLE.md",
|
|
104
|
+
"content": "---\ntype: security_role\ntitle: Administrator Role\ndescription: Security role with full festival operations write access.\ntimestamp: 2026-07-02T00:00:00Z\nname: Administrator\npermissions:\n - \"write:assistant\"\n - \"write:workflow\"\n - \"write:rule\"\n - \"write:domain\"\n - \"write:page\"\n - \"write:security_role\"\n - \"write:task\"\n---\nFull access to all festival operations."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"path": "roles/admin/index.md",
|
|
108
|
+
"content": "# Index — roles/admin\n\n- [Administrator Role](./ROLE.md)\n"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "roles/index.md",
|
|
112
|
+
"content": "# Index — roles\n\n- [admin/](./admin/index.md)\n"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"path": "rules/index.md",
|
|
116
|
+
"content": "# Index — rules\n\n- [Refund Policy](./refund-policy.md)\n"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"path": "rules/refund-policy.md",
|
|
120
|
+
"content": "---\ntype: rule\ntitle: Refund Policy\ndescription: Refund eligibility rule for festival attendees.\ntimestamp: 2026-07-02T00:00:00Z\nname: Refund Policy\nslug: refund-policy\n---\nRefunds are available up to 14 days before the event."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "tasks/index.md",
|
|
124
|
+
"content": "# Index — tasks\n\n- [Ticket 4821 Seat Change](./ticket-4821.md)\n"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"path": "workflows/box-office.md",
|
|
128
|
+
"content": "---\ntype: workflow\ntitle: Box Office\ndescription: Ticket-sales workflow for a music festival.\ntimestamp: 2026-07-02T00:00:00Z\nname: Box Office\nslug: box-office\n---\nSell tickets, then hand the buyer to [[concierge]] for questions."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"path": "workflows/index.md",
|
|
132
|
+
"content": "# Index — workflows\n\n- [Box Office](./box-office.md)\n"
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# `ssss autolink`
|
|
2
|
+
|
|
3
|
+
Generate OKF wiki-links across an SSSS vault. Rewrites bare references to
|
|
4
|
+
`[[slug]]` links so a vault is navigable as an "LLM-wiki," using bundle-relative
|
|
5
|
+
absolute paths. Deterministic and idempotent — running it twice changes nothing.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ssss autolink [dir] # default dir: the current directory
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The same rewrite engine backs provisioning's id-remap (§17.3): when `provision`
|
|
12
|
+
relocates files under a `--prefix`, link targets are recomputed the same way, so
|
|
13
|
+
internal links never dangle after a move.
|
|
14
|
+
|
|
15
|
+
See also: `ssss help provisioning`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# The `.ucw` bundle format (spec §16)
|
|
2
|
+
|
|
3
|
+
A `.ucw` bundle is the transportable package of a vault — "a festival in a box."
|
|
4
|
+
It is plain JSON: a manifest plus the path-sorted vault files, content-hashed for
|
|
5
|
+
integrity. The container file is conventionally named `*.ucw.json`.
|
|
6
|
+
|
|
7
|
+
## Shape
|
|
8
|
+
|
|
9
|
+
```jsonc
|
|
10
|
+
{
|
|
11
|
+
"manifest": {
|
|
12
|
+
"name": "Festival in a Box",
|
|
13
|
+
"description": "...",
|
|
14
|
+
"version": "0.1.0",
|
|
15
|
+
"exported_at": "1970-01-01T00:00:00.000Z", // frozen → deterministic export
|
|
16
|
+
"ssss_core_version": "0.6",
|
|
17
|
+
"required_extensions": ["festech"],
|
|
18
|
+
"export_profile": "sale", // backup | template | sale
|
|
19
|
+
"primitive_inventory": { "workflow": 1, "page": 1, "rule": 1, "assistant": 1, "domain": 1 },
|
|
20
|
+
"provisioning": [ /* steps, see `ssss help provisioning` */ ],
|
|
21
|
+
"parameters": [ /* template variables, see below */ ],
|
|
22
|
+
"file_count": 5,
|
|
23
|
+
"provenance": {
|
|
24
|
+
"content_hash": "sha256:…", // over the canonical file serialization
|
|
25
|
+
"exporter": "@ssss/cli"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [ { "path": "rules/refund-policy.md", "content": "---\n…" } ]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Integrity
|
|
33
|
+
|
|
34
|
+
`provenance.content_hash` is `sha256` over the canonical (path-sorted) serialization
|
|
35
|
+
of `files`. `ssss validate` recomputes it and rejects any mismatch — a bundle cannot
|
|
36
|
+
be silently edited. `primitive_inventory` is registry-driven (a count per `type`),
|
|
37
|
+
not a closed category enum.
|
|
38
|
+
|
|
39
|
+
## Parameters
|
|
40
|
+
|
|
41
|
+
Each entry in `parameters[]` is a template variable resolved at provision time:
|
|
42
|
+
`{ key, label, type, scope, source }` where `source ∈ user | llm | graph | system`.
|
|
43
|
+
Required parameters must be supplied (`ssss provision --param key=value`) or the
|
|
44
|
+
plan is rejected.
|
|
45
|
+
|
|
46
|
+
Commands: `ssss export`, `ssss validate`, `ssss inspect`.
|
|
47
|
+
See also: `ssss help provisioning`, `ssss help portability`.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Conformance (spec §12)
|
|
2
|
+
|
|
3
|
+
A host MUST NOT claim SSSS conformance without passing the canonical suite in
|
|
4
|
+
`conformance/`. It is the shared test every implementation runs.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
ssss conformance # structural + registry portability validation
|
|
8
|
+
ssss conformance --engine # also replay every fixture + round-trip the reference bundle in-process
|
|
9
|
+
ssss conformance --endpoint <url> --token <pat> # run the fixtures against a live host
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What `--engine` proves
|
|
13
|
+
|
|
14
|
+
1. **All Operation Contract fixtures** (`conformance/fixtures.json`) replay through
|
|
15
|
+
the reference engine (`src/engine.mjs`) and produce the expected responses —
|
|
16
|
+
create/patch/event/delete, dry-run, idempotency, and failure cases.
|
|
17
|
+
2. **The reference bundle round-trips**: `validate → provision → import → re-import`
|
|
18
|
+
on `conformance/reference-bundle.ucw.json`, asserting
|
|
19
|
+
- the bundle's schema + content hash are valid,
|
|
20
|
+
- the `sale` profile carries no `tenant_private` file,
|
|
21
|
+
- provision resolves parameters and link integrity,
|
|
22
|
+
- import commits every file, and a second import commits **zero** (idempotent),
|
|
23
|
+
- no `tenant_private` file ever lands on disk.
|
|
24
|
+
3. **Workflow runtime checks** (`src/runtime.mjs`) prove a workflow trigger plans
|
|
25
|
+
deterministic event/task envelopes, duplicate daemon ticks replay idempotently,
|
|
26
|
+
and worker-created runs commit through the Operation Contract.
|
|
27
|
+
|
|
28
|
+
## Endpoint mode
|
|
29
|
+
|
|
30
|
+
`--endpoint` POSTs each fixture's `request` to a host's Operation Contract endpoint
|
|
31
|
+
and diffs the response — this is how festech / ultrachat / total-recall prove they
|
|
32
|
+
implement the *same* standard rather than three drifting copies.
|
|
33
|
+
|
|
34
|
+
See also: `conformance/README.md`, `ssss help runtime`, `ssss help provisioning`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# `ssss export`
|
|
2
|
+
|
|
3
|
+
Package a vault directory into a `.ucw` bundle (spec §16). Pure and deterministic:
|
|
4
|
+
the same vault + profile yields a byte-identical bundle (the timestamp is frozen and
|
|
5
|
+
the files are content-hashed), so exports are diffable and cacheable.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ssss export <vault-dir> [--profile backup|template|sale] [--out file.ucw.json]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Walks every `*.md` under the vault (skipping dotfiles and the `.events` log), reads
|
|
12
|
+
each file's `type` from frontmatter, resolves its portability class (§5.5), and keeps
|
|
13
|
+
only the classes the profile permits. The dropped files are reported with
|
|
14
|
+
`--show-dropped`.
|
|
15
|
+
|
|
16
|
+
Common flags: `--name`, `--description`, `--bundle-version`, `--exporter`,
|
|
17
|
+
`--ext <name>` (declare a required extension, repeatable), `--registry <dir>`.
|
|
18
|
+
|
|
19
|
+
Run `ssss export --help` for the full flag list.
|
|
20
|
+
See also: `ssss help portability`, `ssss help bundle`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# `ssss import`
|
|
2
|
+
|
|
3
|
+
Replay a bundle (or a pre-built plan) into a target vault through the reference
|
|
4
|
+
engine (spec §17.1, §6). Idempotent: each envelope carries a deterministic
|
|
5
|
+
idempotency key, so importing the same bundle twice commits nothing the second time.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ssss import <bundle.ucw.json> --vault <dir> [--param key=value]
|
|
9
|
+
ssss import --plan plan.json --vault <dir> # replay a plan from `ssss provision`
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- `--vault <dir>` is required and is created if missing.
|
|
13
|
+
- Without `--plan`, import provisions inline first (resolving `--param` flags); a
|
|
14
|
+
failed provision (unresolved params / dangling links) aborts before any write.
|
|
15
|
+
- `--dry-run` validates every envelope without committing.
|
|
16
|
+
- The summary reports `committed`, `unchanged (idempotent)`, and `failed` counts.
|
|
17
|
+
|
|
18
|
+
Run `ssss import --help` for the full flag list.
|
|
19
|
+
See also: `ssss help provisioning`, `ssss provision`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# SSSS — overview
|
|
2
|
+
|
|
3
|
+
The **Structured Semantic Syntax System** is a database-free, Markdown-first schema
|
|
4
|
+
and mutation contract for AI-agent state. A vault is a directory of Markdown files
|
|
5
|
+
with YAML frontmatter; every file declares a `type` defined in the registry.
|
|
6
|
+
|
|
7
|
+
`@ssss/cli` is the reference implementation: a dependency-free Operation Contract
|
|
8
|
+
engine, a registry-driven validator, and the `.ucw` bundle/provisioning tooling.
|
|
9
|
+
|
|
10
|
+
## The pieces
|
|
11
|
+
|
|
12
|
+
| Piece | Where | What it is |
|
|
13
|
+
|-------|-------|------------|
|
|
14
|
+
| Spec | `docs/ssss-spec.md` | The normative standard. |
|
|
15
|
+
| Core registry | `registry/core.json` | The 14 document primitives + 5 contract primitives, plus the bundle (§16) and provisioning (§17) schemas. |
|
|
16
|
+
| Engine | `src/engine.mjs` | The §6 Operation Contract pipeline (operation/patch/event/delete). |
|
|
17
|
+
| Runtime | `src/runtime.mjs` | The §11.8 workflow trigger → event/task/run envelope planner. |
|
|
18
|
+
| Bundle | `src/bundle.mjs` | export / validate / provision / import (§16–§17). |
|
|
19
|
+
| Conformance | `conformance/` | Fixtures every host must pass. |
|
|
20
|
+
|
|
21
|
+
## The lifecycle
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
vault ──export──▶ .ucw bundle ──provision──▶ envelope plan ──import──▶ new vault
|
|
25
|
+
(§16, pure) (§17, params + links) (§6, idempotent)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Commands
|
|
29
|
+
|
|
30
|
+
Run `ssss help <topic>` for any of:
|
|
31
|
+
`runtime`, `portability`, `bundle`, `provisioning`, `export`, `provision`, `import`, `conformance`, `autolink`.
|
|
32
|
+
|
|
33
|
+
Run `ssss <command> --help` for: `export`, `validate`, `inspect`, `provision`, `import`, `autolink`, `conformance`.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Portability classification (spec §5.5) — the keystone
|
|
2
|
+
|
|
3
|
+
Every document primitive declares a **portability class**. This is what makes a
|
|
4
|
+
vault sellable without leaking the operator's private data.
|
|
5
|
+
|
|
6
|
+
| Class | Meaning | Example types |
|
|
7
|
+
|-------|---------|---------------|
|
|
8
|
+
| `structural` | The sellable business model — the thing a buyer wants. | `workflow`, `rule`, `page`, `assistant` |
|
|
9
|
+
| `tenant_private` | The operator's private data. **Never** sold or templated. | `task`, customer records |
|
|
10
|
+
| `resource_bound` | Needs a real resource bound at provision time. | `domain`, `phone_number`, `integration_connection` |
|
|
11
|
+
|
|
12
|
+
A file MAY override its type default with `x_portability` in frontmatter. The most
|
|
13
|
+
restrictive of (type default, override) wins.
|
|
14
|
+
|
|
15
|
+
## Export profiles are filters over the classes
|
|
16
|
+
|
|
17
|
+
| Profile | Includes | Use |
|
|
18
|
+
|---------|----------|-----|
|
|
19
|
+
| `backup` | structural + tenant_private + resource_bound | Full operator backup/restore. |
|
|
20
|
+
| `template` | structural + resource_bound | A reusable template, private data stripped. |
|
|
21
|
+
| `sale` | structural + resource_bound | A tradeable business, private data stripped. |
|
|
22
|
+
|
|
23
|
+
> `template` and `sale` exports MUST drop every `tenant_private` primitive. The
|
|
24
|
+
> reference bundle (`conformance/reference-bundle.ucw.json`) proves this: its
|
|
25
|
+
> `task` ticket is dropped from the `sale` export.
|
|
26
|
+
|
|
27
|
+
See also: `ssss help bundle`, `ssss help export`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# `ssss provision`
|
|
2
|
+
|
|
3
|
+
Plan a bundle install (spec §17): resolve parameters, check link integrity under
|
|
4
|
+
id-remap, and emit an ordered list of Operation Contract envelopes. Pure — it never
|
|
5
|
+
touches the filesystem, so it is safe to run and diff before importing.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ssss provision <bundle.ucw.json> --param key=value [--workspace id] [--prefix path] [--out plan.json]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- Required parameters that are neither supplied nor defaulted cause a non-zero exit.
|
|
12
|
+
- Any `[[link]]` that points outside the bundle is reported as a dangling link and
|
|
13
|
+
fails the plan.
|
|
14
|
+
- `--prefix` relocates every file under a target path; link checks follow the remap.
|
|
15
|
+
- Each envelope gets a deterministic idempotency key, so the resulting plan is safe
|
|
16
|
+
to import more than once.
|
|
17
|
+
|
|
18
|
+
Run `ssss provision --help` for the full flag list.
|
|
19
|
+
See also: `ssss help provisioning`, `ssss import`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# The provisioning contract (spec §17)
|
|
2
|
+
|
|
3
|
+
Three deterministic, idempotent verbs move a bundle from an export into a live vault.
|
|
4
|
+
|
|
5
|
+
| Verb | Signature | What it does |
|
|
6
|
+
|------|-----------|--------------|
|
|
7
|
+
| `export` | vault + profile → bundle | Pure. Profile-filtered, content-hashed. |
|
|
8
|
+
| `provision` | bundle + params → plan | Resolves parameters + link integrity + id-remap → an ordered list of Operation Contract envelopes. Touches no filesystem. |
|
|
9
|
+
| `import` | plan + engine → state | Replays each envelope through the §6 engine. Idempotent. |
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
ssss export ./vault --profile sale --out fest.ucw.json
|
|
13
|
+
ssss provision fest.ucw.json --param domain=acme.live --out plan.json
|
|
14
|
+
ssss import --plan plan.json --vault ./new-tenant
|
|
15
|
+
# or in one step:
|
|
16
|
+
ssss import fest.ucw.json --vault ./new-tenant --param domain=acme.live
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Determinism & idempotency (§17.3)
|
|
20
|
+
|
|
21
|
+
- **Id-remap.** `--prefix` relocates every file under a target path; link integrity
|
|
22
|
+
is checked against the remapped target, so `[[links]]` never dangle after a move.
|
|
23
|
+
- **Idempotency keys.** Each envelope's key is `sha256(workspace_id + ':' + path)`,
|
|
24
|
+
truncated. Re-importing the same plan commits nothing new — `import` reports the
|
|
25
|
+
unchanged count.
|
|
26
|
+
- **Link integrity.** `provision` fails closed if any `[[ref]]` points at a file not
|
|
27
|
+
present in the bundle.
|
|
28
|
+
|
|
29
|
+
## Provisioning steps & binding vocabulary (§17.2)
|
|
30
|
+
|
|
31
|
+
`manifest.provisioning[]` describes the real-world resources an importer must wire up.
|
|
32
|
+
Each step: `{ id, label, system, mode, required }`.
|
|
33
|
+
|
|
34
|
+
- `system ∈ workspace | branding | email | phone | domains | accounts | deployments | marketplace | tabs | automation`
|
|
35
|
+
- `mode ∈ existing | provision | install | generate | configure`
|
|
36
|
+
|
|
37
|
+
Graph edges use relations like `uses_brand`, `owns_domain`, `routes_calls_to`,
|
|
38
|
+
`deploys_to`, `installs_pack`. Composition across bundles uses `installMode ∈
|
|
39
|
+
optional | recommended | required`; upgrades are structural-only via `migration` +
|
|
40
|
+
`patch`.
|
|
41
|
+
|
|
42
|
+
Commands: `ssss provision`, `ssss import`.
|
|
43
|
+
See also: `ssss help bundle`, `ssss help portability`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Security roles & RBAC (spec §5.4 security_role, §6.3 Stage 5.5)
|
|
2
|
+
|
|
3
|
+
Every write goes through Stage 5.5 — Granular Authorization — after content
|
|
4
|
+
validation and before commit. It's fail-closed: a write with no verified
|
|
5
|
+
`actor.role` is denied, never silently promoted to a default role.
|
|
6
|
+
|
|
7
|
+
## The `security_role` primitive
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
---
|
|
11
|
+
type: security_role
|
|
12
|
+
name: "editor"
|
|
13
|
+
permissions:
|
|
14
|
+
- "write:workflow"
|
|
15
|
+
- "write:assistant"
|
|
16
|
+
- "read:*"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Can edit workflows and assistants; read-only on everything else.
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Canonical location: `roles/<role>/ROLE.md`, where `<role>` matches the
|
|
23
|
+
`name` field. `permissions` is a flat list — see the grammar below.
|
|
24
|
+
|
|
25
|
+
## Permission grammar
|
|
26
|
+
|
|
27
|
+
| Pattern | Grants |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `write:<type>` | Write access to exactly one primitive type. |
|
|
30
|
+
| `read:<type>` | Read access to exactly one primitive type. |
|
|
31
|
+
| `*:<type>` | Read + write on exactly one primitive type. |
|
|
32
|
+
| `write:*` | Write access to every primitive type, including `event`. |
|
|
33
|
+
| `read:*` | Read access to every primitive type. |
|
|
34
|
+
| `*:*` | Full access. |
|
|
35
|
+
|
|
36
|
+
`event` envelopes have no resolved document type, so they're gated on the
|
|
37
|
+
fixed permission `write:event` specifically — `write:<some other type>`
|
|
38
|
+
does **not** satisfy it, and neither does an unrelated wildcard scoped to a
|
|
39
|
+
document type.
|
|
40
|
+
|
|
41
|
+
## The three non-negotiable role behaviors
|
|
42
|
+
|
|
43
|
+
| `actor.role` | Behavior |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `"system"` | Unconditional bypass. Used by trusted internal callers (the provisioning pipeline stamps every generated envelope this way — see `ssss help provisioning`). Not data-driven; don't expect a `roles/system/ROLE.md`. |
|
|
46
|
+
| `"admin"` | Hardcoded `write:*`/`read:*`, regardless of `roles/admin/ROLE.md`'s content (a file there can only add to this, never restrict it). |
|
|
47
|
+
| *(absent)* | **Denied.** A host that exposes the Operation Contract to untrusted clients MUST overwrite `actor` with verified session identity before the envelope reaches the engine (spec §6.3 Stage 3). A missing `actor.role` is not a default — it's an authorization failure. |
|
|
48
|
+
|
|
49
|
+
Any other role name is resolved by reading `roles/<role>/ROLE.md` from the
|
|
50
|
+
target vault at write time. No file there means zero permissions.
|
|
51
|
+
|
|
52
|
+
## Auditing this yourself
|
|
53
|
+
|
|
54
|
+
The `rbac-fail-open-auditor` agent skill (`.agent/skills/rbac-fail-open-auditor/`)
|
|
55
|
+
builds an adversarial envelope matrix and runs it against the reference
|
|
56
|
+
engine to catch regressions in this logic — including the specific
|
|
57
|
+
historical bug it's named after (a fail-open default that briefly shipped
|
|
58
|
+
in this repo's own uncommitted history; see that skill's
|
|
59
|
+
`references/stage-5-5-rbac-notes.md` for the full case study).
|
|
60
|
+
|
|
61
|
+
See also: `ssss help portability`, `ssss help bundle`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Workflow runtime (spec §11.8)
|
|
2
|
+
|
|
3
|
+
SSSS workflows are runtime definitions, not cron jobs stored somewhere else. The
|
|
4
|
+
canonical schedule lives in the `workflow` primitive's `triggers[]` frontmatter.
|
|
5
|
+
Cron, systemd, serverless schedules, webhooks, browser alarms, and queue workers
|
|
6
|
+
are wake-up mechanisms.
|
|
7
|
+
|
|
8
|
+
## Canonical loop
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
workflow trigger
|
|
12
|
+
-> workflow_triggered event envelope
|
|
13
|
+
-> task operation envelope
|
|
14
|
+
-> task lease / worker claim
|
|
15
|
+
-> run operation or append
|
|
16
|
+
-> task status patch
|
|
17
|
+
-> projection rebuild
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Every mutation goes through the Operation Contract. A daemon MUST NOT write vault
|
|
21
|
+
files directly.
|
|
22
|
+
|
|
23
|
+
## Trigger source of truth
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
---
|
|
27
|
+
type: workflow
|
|
28
|
+
name: "Daily Digest"
|
|
29
|
+
triggers:
|
|
30
|
+
- type: cron
|
|
31
|
+
id: daily-0800
|
|
32
|
+
cron: "0 8 * * *"
|
|
33
|
+
timezone: "America/Denver"
|
|
34
|
+
misfire_policy: run_once
|
|
35
|
+
concurrency: skip_if_running
|
|
36
|
+
isActive: true
|
|
37
|
+
---
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Supported trigger types are `manual`, `cron`, `interval`, `event`, `webhook`,
|
|
41
|
+
`file_change`, and `condition`.
|
|
42
|
+
|
|
43
|
+
## Idempotency
|
|
44
|
+
|
|
45
|
+
Runtime-created work uses this dedupe basis:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
workspace_id + workflow_id + trigger_id + scheduled_for
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Two daemon ticks for the same scheduled instant MUST produce the same task
|
|
52
|
+
idempotency key. This is how SSSS avoids duplicate tasks without making a scheduler
|
|
53
|
+
database canonical.
|
|
54
|
+
|
|
55
|
+
## Reference helpers
|
|
56
|
+
|
|
57
|
+
Use `@ssss/cli/runtime` when building a host daemon:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import { createEngine } from '@ssss/cli/engine';
|
|
61
|
+
import { planWorkflowTrigger } from '@ssss/cli/runtime';
|
|
62
|
+
|
|
63
|
+
const plan = planWorkflowTrigger({
|
|
64
|
+
workflowPath: 'workflows/daily-digest/WORKFLOW.md',
|
|
65
|
+
workflowContent,
|
|
66
|
+
workspaceId: 'ws-1',
|
|
67
|
+
trigger: { type: 'cron', id: 'daily-0800', cron: '0 8 * * *' },
|
|
68
|
+
scheduledFor: '2026-07-02T14:00:00.000Z',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const engine = createEngine();
|
|
72
|
+
for (const envelope of plan.envelopes) {
|
|
73
|
+
engine.processOperation(envelope, './vault');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`ssss conformance --engine` includes runtime checks that prove deterministic task
|
|
78
|
+
planning, idempotent duplicate ticks, and run creation through the reference engine.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# `ssss new` — scaffold a project
|
|
2
|
+
|
|
3
|
+
Create a fresh, ready-to-run repo wired for SSSS (and optionally Total Recall).
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
ssss new my-app # scaffold ./my-app
|
|
7
|
+
ssss new my-app --install # also npm install + run the conformance test
|
|
8
|
+
ssss new my-app --with-total-recall # also wire the Total Recall memory OS
|
|
9
|
+
ssss new my-app --with-total-recall --install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What you get
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
my-app/
|
|
16
|
+
package.json @ssss/cli pinned to this CLI's version tag; npm test = node --test
|
|
17
|
+
vault/ Starter SSSS documents:
|
|
18
|
+
rules/welcome.md (structural)
|
|
19
|
+
workflows/onboarding.md (structural, links [[welcome]])
|
|
20
|
+
assistants/concierge.md (structural)
|
|
21
|
+
tasks/first-task.md (tenant_private — dropped from sale/template exports)
|
|
22
|
+
test/ssss-conformance.test.mjs Replays the canonical fixtures through the engine
|
|
23
|
+
AND round-trips the vault as a sale bundle.
|
|
24
|
+
CLAUDE.md Agent guide (source-of-truth + portability rules).
|
|
25
|
+
README.md .gitignore
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The generated test is **dependency-free** (`node --test`): it proves the toolchain
|
|
29
|
+
implements the Operation Contract (§6) and that the starter vault exports, validates,
|
|
30
|
+
provisions, and re-imports idempotently as a `sale` bundle (§16/§17) — with the
|
|
31
|
+
`tenant_private` task correctly dropped.
|
|
32
|
+
|
|
33
|
+
## Flags
|
|
34
|
+
|
|
35
|
+
| Flag | Effect |
|
|
36
|
+
|------|--------|
|
|
37
|
+
| `--name <s>` | Package name (default: the directory name). |
|
|
38
|
+
| `--with-total-recall` | Add `total-recall-brain` + memory wiring to CLAUDE.md/README. |
|
|
39
|
+
| `--install` | Run `npm install`, Total Recall `init` (if requested), then `npm test`. |
|
|
40
|
+
| `--no-git` | Skip `git init`. |
|
|
41
|
+
| `--ref <git-ref>` | Pin `@ssss/cli` to a specific tag/branch/SHA (default: this CLI's version tag). |
|
|
42
|
+
| `--force` | Scaffold into a non-empty directory. |
|
|
43
|
+
|
|
44
|
+
Shelling out (git/npm/npx) uses `execFileSync` with fixed argument vectors — no shell,
|
|
45
|
+
no interpolation.
|
|
46
|
+
|
|
47
|
+
See also: `ssss help portability`, `ssss help provisioning`, `ssss export`.
|