@mnstry/atelier 0.2.0-alpha.4 → 0.2.0-alpha.6
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 +77 -0
- package/README.md +61 -18
- package/contracts/atelier-repository-observation.v1.schema.json +163 -0
- package/contracts/public-api-baseline.json +57 -0
- package/docs/assurance-controls.md +41 -0
- package/docs/atelier-runtime.md +28 -2
- package/docs/atelier-sync.md +171 -0
- package/docs/blocks/claims.md +23 -12
- package/docs/blocks/will-not-do.md +9 -3
- package/docs/design.md +12 -6
- package/docs/install.md +26 -4
- package/docs/knowledge-graph.md +8 -4
- package/docs/local-services.md +101 -0
- package/docs/release-engineering.md +86 -12
- package/docs/repo-boundary-guard.md +12 -2
- package/docs/upgrade.md +40 -2
- package/fixtures/atelier-repository-observation/invalid/complete-with-blocker.v1.json +18 -0
- package/fixtures/atelier-repository-observation/valid/complete-local.v1.json +48 -0
- package/fixtures/projects/sample-workspace/content/source.html.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/data.json.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/logo.png.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/metrics.csv.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/pipeline.yaml.kg.json +4 -1
- package/package.json +16 -5
- package/skills/claude/atelier-local-service/SKILL.md +47 -0
- package/skills/claude/atelier-public-boundary/SKILL.md +31 -0
- package/skills/codex/atelier-local-service/SKILL.md +47 -0
- package/skills/codex/atelier-public-boundary/SKILL.md +31 -0
- package/src/boundary/content-rules.mjs +283 -20
- package/src/boundary/policy.mjs +162 -72
- package/src/cli/execute-command.mjs +36 -0
- package/src/cli/run.mjs +35 -7
- package/src/collaboration/event-ledger.mjs +365 -0
- package/src/collaboration/index.mjs +17 -0
- package/src/collaboration/proposals.mjs +265 -65
- package/src/commands/attestation.mjs +20 -6
- package/src/commands/disclosure.mjs +133 -0
- package/src/commands/distribution.mjs +2 -1
- package/src/commands/extension-pack.mjs +2 -1
- package/src/commands/init.mjs +2 -1
- package/src/commands/server.mjs +1 -4
- package/src/commands/sync.mjs +100 -0
- package/src/contracts/corpus.mjs +6 -0
- package/src/disclosure/content-scan.mjs +193 -0
- package/src/egress/check.mjs +7 -38
- package/src/egress/forbidden-egress.mjs +32 -18
- package/src/graph/graph.mjs +112 -314
- package/src/graph/knowledge-graph.mjs +94 -18
- package/src/harness/context-client.mjs +9 -1
- package/src/index.mjs +41 -0
- package/src/project/config.mjs +89 -28
- package/src/project/file-class.mjs +14 -0
- package/src/project/package-root.mjs +10 -0
- package/src/project/path-match.mjs +38 -15
- package/src/project/private-state.mjs +110 -0
- package/src/runtime/git-adapter.mjs +189 -0
- package/src/runtime/local-state.mjs +439 -0
- package/src/runtime/repository-observation.mjs +491 -0
- package/src/runtime/supervisor.mjs +788 -0
- package/src/server/local-sidecar.mjs +81 -59
- package/src/server/security.mjs +89 -4
- package/src/server/server.mjs +3 -2
- package/src/support/feedback-report.mjs +4 -3
- package/src/upgrade/upgrade.mjs +2 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Atelier Sync: Deliverable Zero
|
|
2
|
+
|
|
3
|
+
Atelier Sync is the collaborator-facing name for the resident repository
|
|
4
|
+
supervisor. Deliverable Zero is deliberately headless: it proves the Git,
|
|
5
|
+
filesystem, state-machine, recovery, and user-authority boundaries before a
|
|
6
|
+
tray shell or installer is allowed to make the product feel finished.
|
|
7
|
+
|
|
8
|
+
This is repository mechanics, not MNSTRY runtime authority. A Git commit
|
|
9
|
+
changes the enrolled repository. It does not mutate MNSTRY identity, consent,
|
|
10
|
+
visibility, provisioning, commerce, sessions, audit, or any other managed
|
|
11
|
+
runtime object.
|
|
12
|
+
|
|
13
|
+
## Authority contract
|
|
14
|
+
|
|
15
|
+
- Enrollment names exactly one repository. Atelier never scans a home folder.
|
|
16
|
+
- One resolved absolute system Git executable, version, and executable digest
|
|
17
|
+
owns Git semantics for the enrollment. Every inherited `GIT_*` variable is
|
|
18
|
+
stripped from supervised Git calls before Atelier adds its small fixed
|
|
19
|
+
safety environment. Custom SSH transport belongs in the user's SSH config;
|
|
20
|
+
credentials continue through ordinary Git credential helpers. Git `2.40.0`
|
|
21
|
+
or newer is required so global and system attribute provenance is observable.
|
|
22
|
+
- Every cycle observes the full repository. There is no watcher correctness
|
|
23
|
+
dependency in Deliverable Zero.
|
|
24
|
+
- Fetch and fast-forward-only reconciliation are mechanical operations.
|
|
25
|
+
- Commit creation is a two-phase, user-confirmed operation. Planning records
|
|
26
|
+
the head, branch, complete status digest, exact file paths, commit message,
|
|
27
|
+
reviewed blob/mode manifest, diff summary, and exact optional upstream push
|
|
28
|
+
identity. The push identity digest covers the single resolved, normalized,
|
|
29
|
+
credential-free execution destination; persisted display evidence likewise
|
|
30
|
+
strips authentication material, query strings, and fragments. Multiple push
|
|
31
|
+
URLs and `url.*.insteadOf`/`pushInsteadOf` rewrites are refused as ambiguous.
|
|
32
|
+
Every authoritative field is bound into the operation id.
|
|
33
|
+
Execution requires that exact id and refuses if the plan, repository,
|
|
34
|
+
staged bytes/modes, written tree, commit parent/message, or publish target
|
|
35
|
+
changed. A publish plan is refused while any earlier local commit remains
|
|
36
|
+
unpublished, and publication names the exact verified commit object rather
|
|
37
|
+
than a movable `HEAD` ref. Plans expire after 24 hours, are consumed by a
|
|
38
|
+
definitive execution attempt, and are held under resident file/count
|
|
39
|
+
ceilings. Expired, malformed, or oversized retained plan files are removed
|
|
40
|
+
under the repository lock before those ceilings are enforced; redirected
|
|
41
|
+
plan state remains a hard refusal.
|
|
42
|
+
- A commit plan cannot absorb pre-existing staged work. It stages only literal,
|
|
43
|
+
explicitly reviewed paths.
|
|
44
|
+
- Configured Atelier boundary policy is checked against the staged change set
|
|
45
|
+
before commit creation using the enrolled Git executable. When that policy
|
|
46
|
+
declares private-domain ownership, actor verification is blocking even in
|
|
47
|
+
legacy-warning mode. The Sync path disables the boundary command's optional
|
|
48
|
+
network `gh api user` fallback and fails closed when local actor evidence is
|
|
49
|
+
insufficient. Commit history is provenance, not current-user identity, and
|
|
50
|
+
is not accepted as actor evidence on this path. Policies without a declared private-domain owner do not invent
|
|
51
|
+
an actor requirement. Ordinary Git hooks still run; the resulting commit tree,
|
|
52
|
+
single parent, and message must equal the reviewed authority or the local
|
|
53
|
+
commit is rolled back and publication is refused.
|
|
54
|
+
- Push is present only when the reviewed plan requested it, the branch had no
|
|
55
|
+
prior unpublished commits, and HEAD still names the exact verified commit.
|
|
56
|
+
Atelier re-resolves the single push URL immediately before publication and
|
|
57
|
+
pushes the exact commit object directly to that reviewed destination. Push is
|
|
58
|
+
never forced, never follows tags, and never recursively publishes submodule
|
|
59
|
+
refs. When fetch and push resolve to the same credential-free identity,
|
|
60
|
+
Atelier refreshes the exact remote-tracking branch and re-observes before it
|
|
61
|
+
reports `committed-and-published`. A distinct configured push URL is honored,
|
|
62
|
+
but remains an explicit attention state because it cannot prove the fetch
|
|
63
|
+
upstream synchronized. A failed push or post-push tracking refresh preserves
|
|
64
|
+
the local commit, creates one stable attention state, and returns a non-zero
|
|
65
|
+
command exit.
|
|
66
|
+
- Semantic conflict resolution, merge commits, rebase, reset, force push,
|
|
67
|
+
browser apply, broad path scans, telemetry, and hidden upload are absent.
|
|
68
|
+
|
|
69
|
+
## Repository completeness
|
|
70
|
+
|
|
71
|
+
`atelier sync status` emits a supervisor envelope whose `state.observation`
|
|
72
|
+
contains the current `atelier-repository-observation@v1` document. That
|
|
73
|
+
observation cannot report `complete: true` when any of these are unresolved:
|
|
74
|
+
|
|
75
|
+
- lexically identifiable provider-managed, UNC/network, WSL-cross-boundary, or
|
|
76
|
+
unclassified external filesystem roots (mapped-drive classification remains
|
|
77
|
+
an operating-system integration concern for the signed beta);
|
|
78
|
+
- an unsupported Git engine or bare repository;
|
|
79
|
+
- sparse checkout, partial clone, or shallow repository state;
|
|
80
|
+
- tracked paths carrying `assume-unchanged` or `skip-worktree` index flags;
|
|
81
|
+
- missing or unhealthy submodules;
|
|
82
|
+
- required Git LFS content without a working LFS integration, including LFS
|
|
83
|
+
semantics declared by tracked or untracked worktree attributes, repository
|
|
84
|
+
info attributes, and default global or system attributes;
|
|
85
|
+
- an unclassified custom clean, smudge, or process filter;
|
|
86
|
+
- a configured `core.hooksPath` whose executable behavior is outside the
|
|
87
|
+
reviewed repository contract;
|
|
88
|
+
- a remote URL whose authentication shape cannot be classified;
|
|
89
|
+
- multiple push destinations or any configured Git URL rewrite rule;
|
|
90
|
+
- any required Git evidence read that fails, times out, exceeds its budget, or
|
|
91
|
+
cannot be parsed.
|
|
92
|
+
- a change set above the 4,096-entry resident observation ceiling; or
|
|
93
|
+
- a `core.attributesFile` outside the repository-owned/tracked attributes
|
|
94
|
+
boundary whose filter semantics have not been classified.
|
|
95
|
+
|
|
96
|
+
HTTPS through Git Credential Manager, SSH through the user's existing SSH
|
|
97
|
+
configuration, and local test remotes are classified explicitly. Atelier does
|
|
98
|
+
not collect or store provider credentials.
|
|
99
|
+
|
|
100
|
+
## Local operation state
|
|
101
|
+
|
|
102
|
+
Ignored `.atelier-local/runtime/` contains:
|
|
103
|
+
|
|
104
|
+
- `enrollment.json` — exact repository and Git engine;
|
|
105
|
+
- `state.json` — a bounded projection of healthy, attention, or paused state;
|
|
106
|
+
- `control.json` — user pause/freeze state;
|
|
107
|
+
- `plans/` — expiring, consumed reviewed commit plans under count/byte ceilings;
|
|
108
|
+
- `operations.ndjson` — sequence- and hash-chained resident trace with explicit
|
|
109
|
+
hash-bound checkpoints before its byte or record ceiling, with a fresh
|
|
110
|
+
digest-linked generation after a torn or corrupt chain; and
|
|
111
|
+
- an atomic per-repository operation lock.
|
|
112
|
+
|
|
113
|
+
Every directory component is containment-checked and every state leaf is
|
|
114
|
+
opened without following redirects where the platform supports it, with leaf
|
|
115
|
+
type and identity checks on every platform. Stale-lock recovery uses an
|
|
116
|
+
exclusive recovery claim, ages out an abandoned recovery claim after the owner
|
|
117
|
+
grace interval, identity-checks the lock directory before and after quarantine,
|
|
118
|
+
and quarantines only the claimed stale directory; it never recursively deletes
|
|
119
|
+
a newly acquired lock. A live PID without durable process identity cannot wedge
|
|
120
|
+
the repository forever: its owner record becomes recoverable after the 24-hour
|
|
121
|
+
maximum operation age. Enrollment takes the same lock as every other
|
|
122
|
+
authoritative state mutation.
|
|
123
|
+
|
|
124
|
+
Deleting this directory removes convenience and diagnostics. It cannot change
|
|
125
|
+
repository meaning. Git plus readable files remain authoritative.
|
|
126
|
+
|
|
127
|
+
## Engineering commands
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
atelier sync enroll --repo /absolute/path/to/repository
|
|
131
|
+
atelier sync status --repo /absolute/path/to/repository
|
|
132
|
+
atelier sync reconcile --repo /absolute/path/to/repository
|
|
133
|
+
atelier sync run --repo /absolute/path/to/repository --once
|
|
134
|
+
|
|
135
|
+
atelier sync plan \
|
|
136
|
+
--repo /absolute/path/to/repository \
|
|
137
|
+
--path docs/decision.md \
|
|
138
|
+
--message "docs: record decision" \
|
|
139
|
+
--publish
|
|
140
|
+
|
|
141
|
+
# Repeat the exact operation id printed by plan:
|
|
142
|
+
atelier sync commit \
|
|
143
|
+
--repo /absolute/path/to/repository \
|
|
144
|
+
--operation operation-... \
|
|
145
|
+
--confirm operation-...
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`status`, `audit`, `reconcile`, `run --once`, and `commit` return a non-zero
|
|
149
|
+
process exit when their result is not healthy, so automation cannot treat a
|
|
150
|
+
paused state, attention state, or failed publication as success merely because
|
|
151
|
+
JSON was emitted.
|
|
152
|
+
|
|
153
|
+
The future native shell may label the final two commands **Commit & sync**.
|
|
154
|
+
It must not bypass either phase.
|
|
155
|
+
|
|
156
|
+
The repeated operation id is a visible user-intent confirmation gate, not an
|
|
157
|
+
authorization secret. Local software able to read and modify the repository is
|
|
158
|
+
inside the same operating-system trust domain; the control prevents implicit
|
|
159
|
+
or stale execution, not a hostile process with the user's filesystem access.
|
|
160
|
+
|
|
161
|
+
## Evidence boundary
|
|
162
|
+
|
|
163
|
+
Deliverable Zero proves the headless supervisor contract on Linux and macOS,
|
|
164
|
+
with Windows CI covering the portable observation, state, and direct-process
|
|
165
|
+
contract. POSIX executable-wrapper substitution is explicitly skipped on
|
|
166
|
+
Windows; native Windows wrapper-injection proof, signed installation,
|
|
167
|
+
background launch at user login, Windows Home/Pro device behavior, macOS
|
|
168
|
+
notarization, and a nontechnical-user workflow belong to the signed
|
|
169
|
+
collaborator beta. Repositories without an initial commit are not supported by
|
|
170
|
+
this deliverable. A Git executable upgrade changes enrolled identity and
|
|
171
|
+
requires re-enrollment.
|
package/docs/blocks/claims.md
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
This package makes three promises. None of them asks for your trust — each
|
|
2
2
|
one names the command that proves it.
|
|
3
3
|
|
|
4
|
-
**
|
|
5
|
-
telemetry,
|
|
6
|
-
the package. The
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
**There is no silent egress; every network path is named.** There is no
|
|
5
|
+
telemetry, update check, crash reporting, managed-runtime upload, or model
|
|
6
|
+
provider path in the package. The exceptions are explicit: `boundary check`
|
|
7
|
+
may invoke `gh api user` after no declared actor matches an explicit `--actor`,
|
|
8
|
+
`MNSTRY_ATELIER_ACTOR`, `GITHUB_ACTOR`, or a configured Git email; repository
|
|
9
|
+
identity checks may invoke `gh api repos/...` to resolve a canonical GitHub
|
|
10
|
+
identity. Those authenticated requests use your own `gh` credentials. A
|
|
11
|
+
recognized explicit actor prevents the boundary actor fallback; recorded
|
|
12
|
+
repository identities let identity checks keep working when the provider is
|
|
13
|
+
unavailable. Explicitly enrolled Atelier Sync may also run bounded Git fetches
|
|
14
|
+
for observation/reconciliation and one non-force push only when the exact
|
|
15
|
+
reviewed commit plan requested and confirmed it, no earlier local commit is
|
|
16
|
+
waiting to be published, and HEAD still names the verified commit object. Sync
|
|
17
|
+
never uses the network actor fallback, follows tags, or recursively publishes
|
|
18
|
+
submodule refs. The package's HTTP client
|
|
19
|
+
refuses non-loopback URLs, the served pages authorize no external origin, and
|
|
20
|
+
release audit scans every executable or markup file in the exact `npm pack`
|
|
21
|
+
inventory for egress primitives. The standalone gate also scans executable and
|
|
22
|
+
markup files under `src/`, `bin/`, `scripts/`, `templates/`, `examples/`, and
|
|
23
|
+
`skills/`. Two limits worth stating plainly: the egress control does not
|
|
24
|
+
interpret data-only `.json` or `.md` files, and it does not model
|
|
25
|
+
`child_process`; the reviewed `gh` and enrolled Git paths above are documented
|
|
26
|
+
subprocess exceptions rather than scanner detections:
|
|
16
27
|
|
|
17
28
|
```bash
|
|
18
29
|
npm run egress:check
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
- It does not write to a MNSTRY runtime database.
|
|
2
|
-
- It does not import, provision, publish, or send
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
- It does not import, provision, publish, or send project content to a MNSTRY
|
|
3
|
+
managed runtime.
|
|
4
|
+
- Conformance remains offline. Network access is limited to the documented
|
|
5
|
+
`gh` actor-resolution fallback and explicitly enrolled Atelier Sync Git
|
|
6
|
+
operations: bounded fetch for observation/reconciliation, and non-force push
|
|
7
|
+
only when the exact reviewed commit plan requested and confirmed it, no
|
|
8
|
+
earlier local commit remains unpublished, and HEAD still names the verified
|
|
9
|
+
commit object; Sync does not use network actor fallback, follow tags, or
|
|
10
|
+
recursively publish submodule refs.
|
|
5
11
|
- It does not execute model-assisted analysis or any model provider.
|
|
6
12
|
- It does not include client project content.
|
|
7
13
|
|
package/docs/design.md
CHANGED
|
@@ -12,12 +12,16 @@ proves it — because a design document that cannot be checked is marketing.
|
|
|
12
12
|
|
|
13
13
|
## 1. A repository with an ontology
|
|
14
14
|
|
|
15
|
-
A small structured header turns a file into a node: front matter on
|
|
15
|
+
A small structured header turns a file into a governed node: front matter on
|
|
16
16
|
Markdown, or a `.kg.json` sidecar beside any other format — JSON, YAML,
|
|
17
17
|
CSV, media, anything — which the kit enrolls without ever parsing the
|
|
18
18
|
foreign format. The header declares identity (`kg.id`), type, status,
|
|
19
19
|
audience, and relations to other nodes.
|
|
20
20
|
|
|
21
|
+
Markdown without a `kg` block is still counted by the canonical graph engine,
|
|
22
|
+
but only as private `unclassified` material with a diagnostic. Once a `kg`
|
|
23
|
+
block is present, partial or malformed declarations are blocking errors.
|
|
24
|
+
|
|
21
25
|
The graph builder compiles the repository into a knowledge graph,
|
|
22
26
|
deterministically: same tree in, same graph out, and `--check` mode fails
|
|
23
27
|
when a generated graph has drifted from its sources. There is no import
|
|
@@ -92,14 +96,16 @@ atelier lock check --project ./atelier.project.json
|
|
|
92
96
|
The same governed workspace projects two ways.
|
|
93
97
|
|
|
94
98
|
For humans: a generated review surface, served by a sidecar that binds to
|
|
95
|
-
loopback only.
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
loopback only. It requires a generated publication manifest and serves only
|
|
100
|
+
enrolled safe static files after realpath validation. The served pages carry a
|
|
101
|
+
policy that authorizes no external origin, and the only network client in the
|
|
102
|
+
package refuses non-loopback URLs.
|
|
98
103
|
|
|
99
104
|
For agents: session-bound context and capability envelopes that hand an
|
|
100
105
|
agent harness a governed view of the workspace — what exists, what it may
|
|
101
|
-
look at, what it may propose. Proposals are recorded as
|
|
102
|
-
|
|
106
|
+
look at, what it may propose. Proposals are recorded as typed copy-only
|
|
107
|
+
metadata; capability declarations expose no apply endpoint, source write,
|
|
108
|
+
execution, or Git authority. Context
|
|
103
109
|
without authority. Neutral Claude and Codex skill wrappers ship in the
|
|
104
110
|
package, so a harness can do readiness review work against the workspace
|
|
105
111
|
without a single line of custom glue.
|
package/docs/install.md
CHANGED
|
@@ -30,19 +30,19 @@ The registry is the distribution channel of record, as `docs/continuity.md`
|
|
|
30
30
|
commits:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npm install --save-dev @mnstry/atelier@0.2.0-alpha.
|
|
33
|
+
npm install --save-dev @mnstry/atelier@0.2.0-alpha.6
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Installing from the matching Git tag resolves to the same reviewed commit:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npm install --save-dev "git+https://github.com/MNSTRY/atelier.git#v0.2.0-alpha.
|
|
39
|
+
npm install --save-dev "git+https://github.com/MNSTRY/atelier.git#v0.2.0-alpha.6"
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Or over SSH:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npm install --save-dev "git+ssh://git@github.com/MNSTRY/atelier.git#v0.2.0-alpha.
|
|
45
|
+
npm install --save-dev "git+ssh://git@github.com/MNSTRY/atelier.git#v0.2.0-alpha.6"
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Keep the `@mnstry/` scope — see the command-form note above for why the
|
|
@@ -57,6 +57,24 @@ The workspace `atelier.lock.json` should record the resolved version or Git
|
|
|
57
57
|
SHA from the install. Treat the tag or version as the friendly handle and the
|
|
58
58
|
SHA as the review authority.
|
|
59
59
|
|
|
60
|
+
### Adapter runners must bind package identity
|
|
61
|
+
|
|
62
|
+
An early downstream adapter exposed a subtle failure mode worth making a
|
|
63
|
+
general rule: a wrapper that scans arbitrary sibling checkouts and accepts the
|
|
64
|
+
first matching binary can validate against an archived tree while appearing
|
|
65
|
+
current. Adapter and distribution runners must therefore:
|
|
66
|
+
|
|
67
|
+
1. declare one exact `@mnstry/atelier` version in their package manifest;
|
|
68
|
+
2. prefer the installed `node_modules/@mnstry/atelier` package over incidental
|
|
69
|
+
sibling checkouts;
|
|
70
|
+
3. accept an explicit local checkout only when its package name and version
|
|
71
|
+
match the declared dependency;
|
|
72
|
+
4. run `atelier --version` and `atelier lock check` as part of adapter proof;
|
|
73
|
+
5. fail closed when the declared version, resolved package, and lock disagree.
|
|
74
|
+
|
|
75
|
+
This rule binds which Atelier implementation ran. It does not make generated
|
|
76
|
+
output authoritative or grant runtime mutation.
|
|
77
|
+
|
|
60
78
|
Use one private domain repository per user:
|
|
61
79
|
|
|
62
80
|
```text
|
|
@@ -103,7 +121,11 @@ atelier init --template shared-project --target ./project-alpha --actor tenant-u
|
|
|
103
121
|
|
|
104
122
|
`--actor` rewrites the copied boundary policy actor entry and binds it to the
|
|
105
123
|
local Git email when available. Use `--github-login` or `--git-email` to set
|
|
106
|
-
those values explicitly during onboarding.
|
|
124
|
+
those values explicitly during onboarding. At check time, a declared actor is
|
|
125
|
+
resolved in this order: recognized `--actor`/`MNSTRY_ATELIER_ACTOR`/
|
|
126
|
+
`GITHUB_ACTOR`, configured Git email, then a reviewed `gh api user` fallback.
|
|
127
|
+
An explicit value that is not declared in the policy does not authenticate an
|
|
128
|
+
actor and therefore does not suppress later resolution attempts.
|
|
107
129
|
|
|
108
130
|
Then update:
|
|
109
131
|
|
package/docs/knowledge-graph.md
CHANGED
|
@@ -7,16 +7,20 @@ projection readiness.
|
|
|
7
7
|
|
|
8
8
|
## Source Rules
|
|
9
9
|
|
|
10
|
-
- Markdown documents use front matter.
|
|
10
|
+
- Markdown documents may use front matter. A document with no `kg` block is
|
|
11
|
+
represented as `unclassified`, assigned the fail-closed `private` audience,
|
|
12
|
+
and reported diagnostically rather than silently treated as governed.
|
|
11
13
|
- Non-Markdown sources use adjacent `.kg.json` sidecars.
|
|
12
|
-
- `kg.id`
|
|
13
|
-
|
|
14
|
+
- Once a Markdown `kg` block exists, `kg.id` and `kg.audience` are required;
|
|
15
|
+
empty, partial, and malformed declarations are blocking errors.
|
|
14
16
|
- `kg.visibility` is invalid in local source metadata.
|
|
15
17
|
- Declared relations emit semantic edges.
|
|
16
18
|
|
|
17
19
|
## Source formats
|
|
18
20
|
|
|
19
|
-
The graph
|
|
21
|
+
The graph has one canonical classification engine in
|
|
22
|
+
`src/graph/knowledge-graph.mjs`; the older `graph.mjs` surface is a compatibility
|
|
23
|
+
adapter over it, not a second classifier. Markdown front matter is the only inline metadata
|
|
20
24
|
format the kit reads, and every other file becomes a first-class node through
|
|
21
25
|
an adjacent `<file>.kg.json` sidecar
|
|
22
26
|
(`contracts/knowledge-source-sidecar.v1.schema.json`). This is how any format
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Managed local services
|
|
2
|
+
|
|
3
|
+
Atelier-backed repositories sometimes need a local authoring, review, or
|
|
4
|
+
preview service that writes repository-owned state. The service may be
|
|
5
|
+
specialized; its lifecycle and data-boundary behavior should not be improvised.
|
|
6
|
+
|
|
7
|
+
This contract applies to consumer services other than `atelier dev`. It does
|
|
8
|
+
not change the Atelier sidecar's own lifecycle.
|
|
9
|
+
|
|
10
|
+
## Atelier sidecar reference boundary
|
|
11
|
+
|
|
12
|
+
The built-in `atelier dev` sidecar is the reference for its request and
|
|
13
|
+
publication boundary, not for the managed lifecycle below. It binds only to a
|
|
14
|
+
literal loopback host and refuses startup without a valid generated
|
|
15
|
+
`atelier.manifest.json`. Static reads are limited to manifest-enrolled,
|
|
16
|
+
supported file types after realpath containment; hidden, state, secret-shaped,
|
|
17
|
+
symlinked, unknown, and unenrolled paths are denied. API reads require a trusted
|
|
18
|
+
loopback host and `Sec-Fetch-Site: same-origin` or `none`; `same-site` and
|
|
19
|
+
cross-site requests are refused. Mutations additionally require an
|
|
20
|
+
allowed method, exact expected origin, and the session nonce. Its collaboration
|
|
21
|
+
records are copy-only proposals, not an apply channel.
|
|
22
|
+
|
|
23
|
+
## Kit and adapter boundary
|
|
24
|
+
|
|
25
|
+
The portable Atelier layer owns these invariants:
|
|
26
|
+
|
|
27
|
+
- bind to loopback only;
|
|
28
|
+
- expose explicit `start`, `status`, and `stop` operations;
|
|
29
|
+
- detach only when the user asked for a service that survives an agent command;
|
|
30
|
+
- identify the running process with both a random runtime identifier and its
|
|
31
|
+
process ID;
|
|
32
|
+
- refuse to adopt, overwrite, or stop a process whose identity cannot be
|
|
33
|
+
proven;
|
|
34
|
+
- keep runtime records, logs, drafts, and recovery copies in ignored local
|
|
35
|
+
storage with owner-only permissions;
|
|
36
|
+
- make writes atomic and keep a failed queued write from poisoning later saves;
|
|
37
|
+
- keep unsaved browser work available when the service disappears;
|
|
38
|
+
- provide an explicit snapshot export and a retry path;
|
|
39
|
+
- use no telemetry, remote dependency, or external send path.
|
|
40
|
+
|
|
41
|
+
The consuming repository owns its service name, port, executable, state schema,
|
|
42
|
+
content, command names, and user-facing recovery copy. None of those adapter
|
|
43
|
+
details belong in the public Atelier kit.
|
|
44
|
+
|
|
45
|
+
## Lifecycle contract
|
|
46
|
+
|
|
47
|
+
### Start
|
|
48
|
+
|
|
49
|
+
1. Resolve an explicit loopback port and ignored runtime directory.
|
|
50
|
+
2. Probe the service health endpoint.
|
|
51
|
+
3. If a managed instance answers with the recorded runtime identifier and PID,
|
|
52
|
+
report it as already running.
|
|
53
|
+
4. If anything else owns the port, refuse to take it over.
|
|
54
|
+
5. Generate a fresh runtime identifier, start the child without a shell, write
|
|
55
|
+
a mode-0600 runtime record, and wait for health to echo both identifiers.
|
|
56
|
+
6. If health never proves ownership, stop only the child just created and
|
|
57
|
+
report the ignored operational log.
|
|
58
|
+
|
|
59
|
+
### Status
|
|
60
|
+
|
|
61
|
+
Status is healthy only when the runtime record, health response, runtime
|
|
62
|
+
identifier, PID, service identity, and loopback address agree. A responding
|
|
63
|
+
port without that proof is occupied, not adopted.
|
|
64
|
+
|
|
65
|
+
### Stop
|
|
66
|
+
|
|
67
|
+
Stop only the PID whose health response matches the recorded runtime identifier
|
|
68
|
+
and PID. Refuse on disagreement. After a clean stop, remove only the generated
|
|
69
|
+
runtime record. Never kill by port, process name, or broad pattern.
|
|
70
|
+
|
|
71
|
+
Managed start survives a terminal or agent command. It does not imply operating
|
|
72
|
+
system startup. Installing an OS-level service is a separate system change and
|
|
73
|
+
requires explicit user authorization.
|
|
74
|
+
|
|
75
|
+
## Authoring-state contract
|
|
76
|
+
|
|
77
|
+
- The canonical template may be tracked; the live draft must be ignored unless
|
|
78
|
+
a reviewed workflow explicitly promotes a sanitized artifact.
|
|
79
|
+
- Live state and runtime metadata use owner-only permissions.
|
|
80
|
+
- Browser autosave is a recovery layer, not a substitute for the canonical
|
|
81
|
+
local file.
|
|
82
|
+
- A lost server must produce a persistent, actionable message naming the exact
|
|
83
|
+
restart command, the retained browser state, the snapshot option, and Retry.
|
|
84
|
+
- Conflict responses remain fail-closed. Do not silently overwrite a newer
|
|
85
|
+
file or reconcile divergent tabs automatically.
|
|
86
|
+
|
|
87
|
+
## Required evidence
|
|
88
|
+
|
|
89
|
+
A consumer implementation is not complete until tests prove:
|
|
90
|
+
|
|
91
|
+
1. start is idempotent and survives the launching command;
|
|
92
|
+
2. status refuses an unowned listener;
|
|
93
|
+
3. stop is bound to runtime identifier and PID;
|
|
94
|
+
4. a stopped server leaves the exact in-browser draft intact;
|
|
95
|
+
5. restart plus Retry persists that draft;
|
|
96
|
+
6. a refused filesystem write does not break later valid saves;
|
|
97
|
+
7. private state and runtime files are ignored and owner-readable only; and
|
|
98
|
+
8. a fresh checkout can discover the commands through its agent instructions.
|
|
99
|
+
|
|
100
|
+
Use synthetic fixtures for public Atelier tests. Tenant-specific proof remains
|
|
101
|
+
in the tenant repository.
|
|
@@ -10,16 +10,23 @@ a location, never the matched content.
|
|
|
10
10
|
### release:audit
|
|
11
11
|
|
|
12
12
|
`npm run release:audit` (`scripts/check-release-tarball.mjs`) audits the exact
|
|
13
|
-
tarball `npm pack` would publish:
|
|
13
|
+
tarball `npm pack` would publish. `npm run release:candidate` packs once and
|
|
14
|
+
passes the same archive and expected SHA-256 through this audit and both
|
|
15
|
+
consumer smokes:
|
|
14
16
|
|
|
15
17
|
- Package metadata: name, license, exposed CLI bins, and a mandatory `files`
|
|
16
18
|
allowlist in `package.json`.
|
|
17
19
|
- Tarball allowlist: every packed path must match a known-good pattern; any
|
|
18
|
-
unexpected file fails the audit.
|
|
20
|
+
unexpected file fails the audit. The extracted archive inventory must match
|
|
21
|
+
the `npm pack --json` inventory exactly.
|
|
19
22
|
- Content scan: every packed file is scanned against committed structural
|
|
20
23
|
patterns (absolute user paths, machine-local temp paths, agent-local state
|
|
21
24
|
paths, key material, secret-like assignments) and against the maintainer-held
|
|
22
25
|
denylist described below.
|
|
26
|
+
- Egress scan: the canonical egress control receives the exact `npm pack`
|
|
27
|
+
inventory and inspects every packed executable or markup file, including a
|
|
28
|
+
test-shaped path if one is ever admitted to the artifact. Packed test-fixture
|
|
29
|
+
suppression markers are refused; reviewed local-computed markers are counted.
|
|
23
30
|
- Version drift: `CHANGELOG.md` must contain a `## <version>` heading and
|
|
24
31
|
`README.md` must mention the version. The expected version and tarball name
|
|
25
32
|
are derived from `package.json`, never hardcoded.
|
|
@@ -27,6 +34,15 @@ tarball `npm pack` would publish:
|
|
|
27
34
|
Exit codes: `0` clean, `1` findings, `2` configuration error (for example an
|
|
28
35
|
unavailable denylist without explicit acknowledgment).
|
|
29
36
|
|
|
37
|
+
`release:candidate` additionally requires a clean tree, records the candidate
|
|
38
|
+
commit and tarball digest, and refuses a version already bound to a different
|
|
39
|
+
tagged commit. It is a release-evidence command, not a publication command.
|
|
40
|
+
When `ATELIER_RELEASE_OUTPUT_DIR` is set, it atomically retains the verified
|
|
41
|
+
tarball, npm-pack metadata, and a machine-readable receipt. The trusted
|
|
42
|
+
publishing workflow runs `prepublishOnly` explicitly with that output directory,
|
|
43
|
+
re-verifies the retained digest, and publishes the retained tarball path rather
|
|
44
|
+
than repacking the source checkout.
|
|
45
|
+
|
|
30
46
|
### repo:check
|
|
31
47
|
|
|
32
48
|
`npm run repo:check` (`scripts/check-repo-disclosure.mjs`) sweeps the whole
|
|
@@ -43,6 +59,27 @@ Git-tracked tree, not just the tarball:
|
|
|
43
59
|
Exit codes match `release:audit`: `0` clean, `1` findings, `2` configuration or
|
|
44
60
|
usage error.
|
|
45
61
|
|
|
62
|
+
### disclosure check
|
|
63
|
+
|
|
64
|
+
`atelier disclosure check` is the portable consumer-facing content gate. It
|
|
65
|
+
scans every tracked text file by default or the exact staged index with
|
|
66
|
+
`--staged`, never follows tracked symlinks, and reports labels plus locations
|
|
67
|
+
without echoing matched content. `--untrusted` suppresses finding details.
|
|
68
|
+
|
|
69
|
+
The command loads private patterns from `ATELIER_DENYLIST_JSON`, an explicit
|
|
70
|
+
`--denylist` path, or ignored
|
|
71
|
+
`.atelier-local/disclosure-denylist.json`. A repository-local denylist is
|
|
72
|
+
refused if it is tracked or not covered by `.gitignore`. Missing private
|
|
73
|
+
patterns are a configuration failure unless `--structural-only` explicitly
|
|
74
|
+
acknowledges the reduced verdict. Public text-only packaging can also use
|
|
75
|
+
`--fail-on-binary`; Atelier's own tarball audit separately refuses packed
|
|
76
|
+
binary files.
|
|
77
|
+
|
|
78
|
+
The public Atelier repository keeps the stronger `repo:check` identity and
|
|
79
|
+
commit-message controls. The portable command exists so consumer repositories
|
|
80
|
+
can enforce the same public/private content boundary without inheriting
|
|
81
|
+
MNSTRY-specific commit identities.
|
|
82
|
+
|
|
46
83
|
### Commit-identity gate
|
|
47
84
|
|
|
48
85
|
Part of `repo:check --commits`. Commit authors must match a hardcoded
|
|
@@ -65,18 +102,52 @@ changelog and the migration registry honest about breaking changes:
|
|
|
65
102
|
- Every registered migration record is re-validated against the migration
|
|
66
103
|
record contract.
|
|
67
104
|
|
|
105
|
+
### public-api:compat
|
|
106
|
+
|
|
107
|
+
`npm run public-api:compat` compares every package subpath and named JavaScript
|
|
108
|
+
export published by `v0.2.0-alpha.4` with the current package. Removing one
|
|
109
|
+
fails closed. It also rejects modified source that retains the already-tagged
|
|
110
|
+
baseline version, independently of the release-candidate check. The baseline
|
|
111
|
+
records and verifies its tag commit and the public npm artifact identity; the
|
|
112
|
+
published archive was independently checked to contain all 20 subpaths and 212
|
|
113
|
+
named exports. This is runtime JavaScript shape continuity, not a promise about
|
|
114
|
+
function signatures, types, or behavior.
|
|
115
|
+
|
|
68
116
|
### egress:check
|
|
69
117
|
|
|
70
118
|
`npm run egress:check` (`atelier egress check`) scans package runtime paths for
|
|
71
|
-
forbidden non-localhost egress. The package claims no
|
|
72
|
-
|
|
119
|
+
forbidden non-localhost HTTP egress primitives. The package claims no silent or
|
|
120
|
+
undocumented runtime egress; this gate is one mechanical check behind that
|
|
121
|
+
claim. It does not interpret data-only Markdown/JSON and does not model
|
|
122
|
+
`child_process`, so the reviewed `gh` identity-resolution subprocesses and the
|
|
123
|
+
explicitly enrolled Atelier Sync Git fetch/non-force-push subprocesses are
|
|
124
|
+
documented exceptions backed by dedicated refusal tests. Sync refuses fetch on
|
|
125
|
+
an incomplete observation, refuses publish while prior local commits are
|
|
126
|
+
unpublished, strips repository/config retargeting environment variables, and
|
|
127
|
+
pushes the exact post-hook-verified commit object without following tags or
|
|
128
|
+
recursively publishing submodule refs. Its boundary check also suppresses the
|
|
129
|
+
optional network actor fallback.
|
|
73
130
|
|
|
74
131
|
### consumer:smoke
|
|
75
132
|
|
|
76
133
|
`npm run consumer:smoke` (`scripts/consumer-smoke.mjs`) packs the real tarball,
|
|
77
134
|
installs it offline into a throwaway consumer project with lifecycle scripts
|
|
78
|
-
disabled
|
|
79
|
-
|
|
135
|
+
disabled and without copying the publisher's `overrides`, checks the installed
|
|
136
|
+
dependency tree, imports every declared JavaScript export, parses every
|
|
137
|
+
declared JSON export, and validates a sample export through both API and CLI.
|
|
138
|
+
It proves the tarball is installable and functional exactly as a bare consumer
|
|
139
|
+
receives it from disk. The offline smoke deliberately warms the locked registry
|
|
140
|
+
dependency closure first; it does not prove that a not-yet-published version
|
|
141
|
+
resolves from a cold or live registry.
|
|
142
|
+
|
|
143
|
+
### assurance:mutation-smoke
|
|
144
|
+
|
|
145
|
+
`npm run assurance:mutation-smoke` runs local, synthetic negative controls for
|
|
146
|
+
the boundary, graph, packed and direct egress, sidecar, and distribution
|
|
147
|
+
families. Every fixture introduces one named failure and must be refused by the
|
|
148
|
+
terminal CLI or release command where one exists. This is part of
|
|
149
|
+
`prepublishOnly`; a control that stops detecting its failure mode blocks the
|
|
150
|
+
release even if positive-path tests remain green.
|
|
80
151
|
|
|
81
152
|
### Egress-marker inventory
|
|
82
153
|
|
|
@@ -105,7 +176,7 @@ maintainer-reviewed before entering the list.
|
|
|
105
176
|
Four jobs run on pushes to `main` and on pull requests, and all four are
|
|
106
177
|
required status checks:
|
|
107
178
|
|
|
108
|
-
- `test`: syntax check (`node --check`, not a type system), the full test suite, contract checks, `egress:check`, and
|
|
179
|
+
- `test`: syntax check (`node --check`, not a type system), the full test suite (including isolated consumer disclosure-command proofs), contract checks, `egress:check`, `assurance:mutation-smoke`, and
|
|
109
180
|
`migrations:check`. This job sets `ATELIER_ALLOW_MISSING_DENYLIST=1` scoped
|
|
110
181
|
to the job only — denylist assertions belong to the secret lane.
|
|
111
182
|
- `consumer-smoke`: warms the npm cache with `npm ci` (the offline tarball
|
|
@@ -127,11 +198,14 @@ the only safe block.
|
|
|
127
198
|
|
|
128
199
|
To clear a fork pull request, a maintainer verifies the head SHA and dispatches
|
|
129
200
|
the `fork-sweep` workflow with the pull-request number and that SHA. The
|
|
130
|
-
workflow
|
|
131
|
-
out as data — it never installs or executes
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
201
|
+
workflow pins the trusted scanner checkout to the protected default branch and
|
|
202
|
+
runs it against the fork checked out as data — it never installs or executes
|
|
203
|
+
anything from the untrusted tree. It requires an open PR whose base repository
|
|
204
|
+
and branch are the protected default, pins the base and head SHAs from GitHub,
|
|
205
|
+
scans the complete bounded base-to-head object range while waiving only
|
|
206
|
+
repository-specific commit identity, re-verifies that the head SHA has not
|
|
207
|
+
moved, and posts a `secret-sweep` check run on the SHA. The newest check run
|
|
208
|
+
with that name supersedes the earlier failure for branch protection.
|
|
135
209
|
|
|
136
210
|
`release:audit` never runs against untrusted code (`npm pack` executes
|
|
137
211
|
lifecycle scripts); it re-runs on the push build of the merge commit. No
|
|
@@ -170,12 +170,22 @@ machine for weeks.
|
|
|
170
170
|
- `pre-push` runs `atelier boundary push-check` — git writes the ref updates to
|
|
171
171
|
the hook's stdin, and only that range is judged. A brand-new branch is diffed
|
|
172
172
|
against the empty tree, so nothing slips through unscanned.
|
|
173
|
-
- `atelier boundary audit` scans the
|
|
174
|
-
|
|
173
|
+
- `atelier boundary audit` scans the current working tree by default and
|
|
174
|
+
**reports without blocking**, listing matches, incomplete-read diagnostics,
|
|
175
|
+
and declared exceptions with their reasons. Use `--head` for a committed
|
|
176
|
+
snapshot. The output names its source so a dirty tree cannot be mistaken for
|
|
177
|
+
`HEAD` evidence.
|
|
175
178
|
|
|
176
179
|
If the guard cannot work out which repo it is running in, it fails closed. A
|
|
177
180
|
guard that silently judges nothing is worse than one that stops you.
|
|
178
181
|
|
|
182
|
+
Path scopes are segment-aware globs: `*` does not cross `/`, `**` does, and
|
|
183
|
+
patterns are matched against normalized repository-relative paths. Explicitly
|
|
184
|
+
declaring `contentRules: []` is invalid; omit the field to receive defaults.
|
|
185
|
+
Git diff output and binary reads have per-file and aggregate budgets. A failed,
|
|
186
|
+
truncated, oversized, or unparsable evidence read produces a blocking
|
|
187
|
+
completeness diagnostic rather than a partial clean verdict.
|
|
188
|
+
|
|
179
189
|
### Declaring an exception
|
|
180
190
|
|
|
181
191
|
Exceptions live in the boundary policy, not in the guard script. A repo-specific
|