artifacty 0.11.1 → 0.13.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/CLAUDE.md +10 -4
- package/README.md +164 -24
- package/SECURITY.md +25 -16
- package/docs/artifact-schema-v1.md +73 -50
- package/docs/central-team-deployment-design.md +56 -52
- package/docs/integrations.md +29 -25
- package/docs/mcp-public-api.md +75 -57
- package/docs/network-sharing.md +8 -8
- package/docs/release-checklist.md +29 -13
- package/docs/roadmap-design.md +145 -133
- package/docs/sarif-csv-artifact-plan.md +25 -26
- package/docs/threat-model.md +121 -100
- package/docs/upgrade-backups.md +89 -0
- package/docs/writing-style.md +56 -0
- package/package.json +5 -3
- package/src/cli.js +78 -3
- package/src/lib/backup.js +19 -6
- package/src/lib/doctor.js +1 -1
- package/src/lib/i18n.js +142 -0
- package/src/lib/network-policy.js +234 -0
- package/src/lib/render.js +142 -28
- package/src/lib/sample-content.js +191 -0
- package/src/lib/samples.js +74 -0
- package/src/lib/share-links.js +136 -0
- package/src/lib/storage.js +458 -45
- package/src/lib/upgrade-backup.js +417 -0
- package/src/mcp-server.js +18 -6
- package/src/server.js +198 -7
package/docs/threat-model.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Threat Model
|
|
2
2
|
|
|
3
|
-
Artifacty is a local artifact exchange for LLM agents.
|
|
4
|
-
operator, one local store, and trusted local MCP clients
|
|
3
|
+
Artifacty is a local artifact exchange for LLM agents. Its default deployment
|
|
4
|
+
uses one operator, one local store, and trusted local MCP clients.
|
|
5
5
|
|
|
6
6
|
## Assets
|
|
7
7
|
|
|
@@ -14,8 +14,8 @@ operator, one local store, and trusted local MCP clients by default.
|
|
|
14
14
|
|
|
15
15
|
## Trust Boundaries
|
|
16
16
|
|
|
17
|
-
- **HTTP browser server**: local by default
|
|
18
|
-
|
|
17
|
+
- **HTTP browser server**: local by default. An operator can configure access
|
|
18
|
+
from LAN or team networks.
|
|
19
19
|
- **MCP stdio server**: local process launched by an MCP client. It inherits the
|
|
20
20
|
local user account's filesystem permissions. In bridge mode, it forwards
|
|
21
21
|
JSON-RPC to a configured central `/mcp` endpoint instead of touching local
|
|
@@ -58,8 +58,11 @@ Controls:
|
|
|
58
58
|
- Personal API tokens are stored only as hashes.
|
|
59
59
|
- Browser sessions use `HttpOnly` and `SameSite=Lax` cookies.
|
|
60
60
|
|
|
61
|
-
Guidance:
|
|
62
|
-
|
|
61
|
+
Guidance:
|
|
62
|
+
|
|
63
|
+
- Rotate tokens after sharing sessions.
|
|
64
|
+
- Use token headers in scripts.
|
|
65
|
+
- Use generated startup tokens only for temporary interactive shares.
|
|
63
66
|
|
|
64
67
|
### Cross-Site Request Forgery
|
|
65
68
|
|
|
@@ -97,12 +100,12 @@ Risk: agents may accidentally publish API keys or private keys into artifacts.
|
|
|
97
100
|
|
|
98
101
|
Controls:
|
|
99
102
|
|
|
100
|
-
-
|
|
103
|
+
- Artifacty scans common API key and private key patterns before storage.
|
|
101
104
|
- Writes fail unless `allowSecrets` or `ARTIFACTY_ALLOW_SECRETS=true` is set.
|
|
102
|
-
-
|
|
105
|
+
- Artifacty records the scan status in version metadata.
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
Limitation: pattern scanning can miss sensitive data. A successful scan does
|
|
108
|
+
not prove that content is safe to share.
|
|
106
109
|
|
|
107
110
|
### MCP Tool Abuse
|
|
108
111
|
|
|
@@ -120,23 +123,25 @@ Controls:
|
|
|
120
123
|
- MCP writes go through the same secret scan and audit paths as CLI/HTTP writes.
|
|
121
124
|
- MCP resources are read-only.
|
|
122
125
|
|
|
123
|
-
Guidance:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
Guidance:
|
|
127
|
+
|
|
128
|
+
- Install Artifacty MCP only in trusted clients and workspaces.
|
|
129
|
+
- For central deployments, use TLS through a reverse proxy.
|
|
130
|
+
- Rotate shared tokens after team changes.
|
|
126
131
|
|
|
127
132
|
### Personal API Token Scopes
|
|
128
133
|
|
|
129
|
-
Risk:
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
Risk: an attacker can use a leaked personal API token. A read-only reporting
|
|
135
|
+
token should not permit artifact changes or access to admin routes, such as
|
|
136
|
+
backup and webhooks.
|
|
132
137
|
|
|
133
138
|
Controls:
|
|
134
139
|
|
|
135
140
|
- Each personal token carries a `scopes_json` list drawn from `read`,
|
|
136
141
|
`write`, `admin` (default `["read", "write"]` for both new tokens and
|
|
137
142
|
tokens created before scopes existed).
|
|
138
|
-
-
|
|
139
|
-
|
|
143
|
+
- Only a user with the admin role can own a token with the `admin` scope.
|
|
144
|
+
`createApiToken` rejects other requests for this scope.
|
|
140
145
|
- `requireScope` (`src/lib/security.js`) is called on every `/api/*` HTTP
|
|
141
146
|
route: read routes need `read`, mutating routes need `write`, and
|
|
142
147
|
admin-only routes (`/api/webhooks*`, `/api/admin/backup*`) need `admin` in
|
|
@@ -145,22 +150,20 @@ Controls:
|
|
|
145
150
|
throttled to one per token per minute.
|
|
146
151
|
- The shared `ARTIFACTY_API_TOKEN` and browser sessions always have full
|
|
147
152
|
scopes — scoping only narrows a *personal* token.
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Guidance: issue read-only tokens to reporting/analytics integrations, and
|
|
158
|
-
reserve `admin` scope tokens for operator tooling only.
|
|
153
|
+
- For HTTP MCP, `tools/list` omits write tools when the token lacks `write`.
|
|
154
|
+
A direct call to one of these tools returns an `isError` result with
|
|
155
|
+
`structuredContent.code: "scope_denied"`. The tool does not execute.
|
|
156
|
+
- Local stdio is a trusted local process and does not enforce token scopes.
|
|
157
|
+
If its configured token identifies a personal account, artifact access rules
|
|
158
|
+
still apply to that account. Private site mode requires that personal identity.
|
|
159
|
+
|
|
160
|
+
Guidance: issue read-only tokens to reporting and analytics integrations.
|
|
161
|
+
Reserve tokens with the `admin` scope for operator tools.
|
|
159
162
|
|
|
160
163
|
### HTTP and MCP Rate Limiting
|
|
161
164
|
|
|
162
|
-
Risk: a compromised or
|
|
163
|
-
|
|
165
|
+
Risk: a compromised or faulty client could send excessive writes or searches.
|
|
166
|
+
An attacker could also send repeated password guesses to `/login`.
|
|
164
167
|
|
|
165
168
|
Controls:
|
|
166
169
|
|
|
@@ -184,29 +187,28 @@ Controls:
|
|
|
184
187
|
- The limiter is in-memory and per-process; it resets on restart and does
|
|
185
188
|
not coordinate across multiple server processes sharing one store.
|
|
186
189
|
|
|
187
|
-
Guidance:
|
|
188
|
-
|
|
189
|
-
non-loopback bind.
|
|
190
|
+
Guidance: increase the `*_PER_MIN` environment variables for integrations that
|
|
191
|
+
need higher throughput. Keep rate limiting enabled on non-loopback interfaces.
|
|
190
192
|
|
|
191
193
|
### Request and Content Size Limits
|
|
192
194
|
|
|
193
|
-
Artifacty enforces the following byte limits
|
|
194
|
-
of
|
|
195
|
+
Artifacty enforces the following byte limits in its server process. These
|
|
196
|
+
limits are independent of reverse proxy limits:
|
|
195
197
|
|
|
196
198
|
| Limit | Value | Constant / env |
|
|
197
199
|
| --- | --- | --- |
|
|
198
200
|
| Artifact version content | 16 MiB | `MAX_ARTIFACT_BYTES` (`src/lib/storage.js`) |
|
|
199
201
|
| Backup import body | see `src/lib/backup.js` | `MAX_BACKUP_BYTES` |
|
|
200
|
-
| Comment body
|
|
202
|
+
| Comment body | 16 KiB | `MAX_COMMENT_BYTES` (`src/lib/storage.js`) |
|
|
201
203
|
| Generic JSON/form request body | `MAX_ARTIFACT_BYTES + 1024` | default `limitBytes` in `readJsonBody`/`readFormBody` (`src/server.js`) |
|
|
202
204
|
|
|
203
|
-
|
|
205
|
+
Artifacty rejects a request body over its limit with `413` before parsing it.
|
|
204
206
|
|
|
205
207
|
### Webhook SSRF and Secret Handling
|
|
206
208
|
|
|
207
|
-
Risk: a webhook
|
|
208
|
-
from the Artifacty server
|
|
209
|
-
|
|
209
|
+
Risk: an attacker who controls a webhook URL can influence outbound HTTP
|
|
210
|
+
requests from the Artifacty server. A leaked webhook secret lets an attacker
|
|
211
|
+
forge signed deliveries.
|
|
210
212
|
|
|
211
213
|
Controls:
|
|
212
214
|
|
|
@@ -234,9 +236,8 @@ Controls:
|
|
|
234
236
|
records changed after the webhook was created) is not caught by this
|
|
235
237
|
control. Treat webhook creation as an admin-only, trusted-input operation,
|
|
236
238
|
not as safe to expose to untrusted callers.
|
|
237
|
-
- Deliveries use `redirect: "manual"` and never follow
|
|
238
|
-
|
|
239
|
-
otherwise-blocked address.
|
|
239
|
+
- Deliveries use `redirect: "manual"` and never follow redirects. A webhook
|
|
240
|
+
target cannot use a 3xx response to send delivery to a blocked address.
|
|
240
241
|
- The webhook secret is shown once, in the create response, and never stored
|
|
241
242
|
or returned again in plaintext. What is persisted is `secretHash =
|
|
242
243
|
sha256(secret)`, and every delivery is signed as
|
|
@@ -249,74 +250,97 @@ Controls:
|
|
|
249
250
|
single-user mode (no accounts configured) it is available to whoever holds
|
|
250
251
|
the configured API token, matching every other write route's trust
|
|
251
252
|
boundary.
|
|
252
|
-
- After 20 consecutive delivery failures
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
- After 20 consecutive delivery failures, Artifacty disables the webhook and
|
|
254
|
+
writes a `webhook-deliver-failed` audit row. The webhook stays disabled until
|
|
255
|
+
an administrator deletes and recreates it.
|
|
256
|
+
|
|
257
|
+
Guidance:
|
|
255
258
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
- Register only webhook endpoints that you control or trust.
|
|
260
|
+
- Prefer HTTPS targets.
|
|
261
|
+
- If you suspect secret exposure, delete the webhook.
|
|
262
|
+
- Recreate the webhook with a new secret. This also rotates its signing
|
|
263
|
+
`secretHash`.
|
|
260
264
|
|
|
261
265
|
### Artifact Visibility and Ownership
|
|
262
266
|
|
|
263
|
-
Risk:
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
Risk: one user could read or change another user's artifacts without permission.
|
|
268
|
+
This includes sensitive drafts that the owner did not intend to share.
|
|
269
|
+
|
|
270
|
+
Controls:
|
|
271
|
+
|
|
272
|
+
- Administrators select public or private site mode at `/admin/access`.
|
|
273
|
+
- In public mode, every artifact has `visibility` (`private` or `team`, default
|
|
274
|
+
`team`) and an `ownerUserId`. Only the owner or an administrator can read or
|
|
275
|
+
write `private` artifacts through normal artifact routes. Anonymous browser
|
|
276
|
+
visitors can read `team` artifacts. Authenticated principals can write them.
|
|
277
|
+
API authentication requirements still apply. `ARTIFACTY_TEAM_WRITE=owner` restricts these writes to owners and
|
|
278
|
+
administrators.
|
|
279
|
+
- Private site mode requires a personal identity. Owners and administrators
|
|
280
|
+
retain access. Other users need a direct or team grant. Grants permit
|
|
281
|
+
reading, commenting, or editing. Artifacty applies the strongest matching
|
|
282
|
+
grant. Token scopes impose an additional restriction.
|
|
283
|
+
- Archiving, restoring, sharing, and changes to visibility or ownership require
|
|
284
|
+
the owner or an administrator. These rules apply in both site modes.
|
|
285
|
+
- If a caller cannot read an artifact, the server returns
|
|
286
|
+
`404`/`ARTIFACT_NOT_FOUND`. This prevents disclosure of the artifact's
|
|
287
|
+
existence. If the caller can read it but lacks the required write or management
|
|
288
|
+
permission, the server returns `403` with `code: "forbidden"`.
|
|
289
|
+
- List queries apply access checks in SQL for both metadata and FTS search.
|
|
290
|
+
Relations to unreadable targets return `{ restricted: true }` without the
|
|
291
|
+
target summary.
|
|
292
|
+
- A shared `ARTIFACTY_API_TOKEN` has no personal identity. In public mode, it can
|
|
293
|
+
read and write `team` artifacts but cannot see `private` artifacts. In private
|
|
294
|
+
mode, it cannot read or create artifacts. Its administrative privileges on
|
|
295
|
+
other server routes do not grant a personal artifact identity.
|
|
296
|
+
- In public mode with no user accounts, user access checks do not apply.
|
|
297
|
+
|
|
298
|
+
Guidance: use separate stores for mutually untrusted parties. Administrators can
|
|
299
|
+
read, write, and reassign any artifact in their store.
|
|
300
|
+
|
|
301
|
+
### Public Share Links and Network Restrictions
|
|
302
|
+
|
|
303
|
+
Risk: a copied share link can disclose an artifact to anyone who holds the link.
|
|
304
|
+
An incorrect network policy can either expose the server or lock out its
|
|
305
|
+
administrator.
|
|
266
306
|
|
|
267
307
|
Controls:
|
|
268
308
|
|
|
269
|
-
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
as `{ restricted: true }` instead of the target's summary.
|
|
285
|
-
- A shared `ARTIFACTY_API_TOKEN` (or any request before the first user
|
|
286
|
-
account exists) has no personal identity and is treated as an anonymous
|
|
287
|
-
team principal: it can read and write `team` artifacts but never sees
|
|
288
|
-
`private` ones, even though it is admin-equivalent for server
|
|
289
|
-
administration routes elsewhere.
|
|
290
|
-
- In single-user mode (no user accounts configured at all) every check is
|
|
291
|
-
bypassed, matching pre-Section-10 behavior, since there is no second
|
|
292
|
-
identity to protect against.
|
|
293
|
-
|
|
294
|
-
Guidance: treat `private` as a convenience boundary between cooperating,
|
|
295
|
-
already-authenticated users on one server, not a substitute for running
|
|
296
|
-
separate stores for genuinely untrusted parties — an admin account can
|
|
297
|
-
always read, write, and reassign ownership of any artifact.
|
|
309
|
+
- Share links provide read-only access. The owner or an administrator creates
|
|
310
|
+
and revokes them. A link can select the latest version or one fixed version.
|
|
311
|
+
- Links expire. Private site mode disables them unless an administrator enables
|
|
312
|
+
them. The server stores token hashes and shows the raw token only at creation.
|
|
313
|
+
- Share pages omit artifact ownership, tags, history, and internal artifact URLs.
|
|
314
|
+
They use `Referrer-Policy: no-referrer` and `Cache-Control: no-store`.
|
|
315
|
+
- All HTTP requests, including share links, obey the configured IP/CIDR allowlist.
|
|
316
|
+
The server checks the TCP peer address and ignores forwarding headers.
|
|
317
|
+
- A network change must include the administrator's current address. It remains
|
|
318
|
+
pending until confirmed. If it expires without confirmation, Artifacty restores
|
|
319
|
+
the previous policy. Administrators can also roll back a pending change.
|
|
320
|
+
|
|
321
|
+
Guidance: treat share links as credentials. Revoke a link if it reaches an
|
|
322
|
+
unintended recipient. When using a reverse proxy, account for its TCP peer
|
|
323
|
+
address in the network policy.
|
|
298
324
|
|
|
299
325
|
### Retention Purge Gate
|
|
300
326
|
|
|
301
|
-
Risk:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
can trigger.
|
|
327
|
+
Risk: an incorrect retention policy can permanently delete artifacts and their
|
|
328
|
+
version files. For example, an operator could set `purgeArchivedAfterDays` too
|
|
329
|
+
low or apply it without reviewing the affected artifacts. Purge is the only
|
|
330
|
+
irreversible action that retention settings can trigger.
|
|
306
331
|
|
|
307
332
|
Controls:
|
|
308
333
|
|
|
309
|
-
-
|
|
310
|
-
`
|
|
311
|
-
|
|
312
|
-
`artifacty retention run`.
|
|
334
|
+
- Changing `archiveAfterDays`, `purgeArchivedAfterDays`, `auditRetentionDays`,
|
|
335
|
+
`eventRetentionRows`, or `keepTags` does not delete data. The new policy takes
|
|
336
|
+
effect on the next sweep or explicit `artifacty retention run`.
|
|
313
337
|
- `artifacty retention run` and `POST /api/admin/retention/run` default to
|
|
314
338
|
`dryRun: true`, returning a report of what would be archived/purged/pruned
|
|
315
339
|
without changing the store. `/admin/retention` renders that same report so
|
|
316
340
|
an admin can review it before applying anything.
|
|
317
|
-
- Archiving
|
|
318
|
-
`artifacty restore`
|
|
319
|
-
|
|
341
|
+
- Archiving removes an artifact from active lists without deleting content.
|
|
342
|
+
`artifacty restore` reverses it. The existing owner or administrator check
|
|
343
|
+
on `archiveArtifact` is the only access requirement.
|
|
320
344
|
- Purging is irreversible and additionally requires
|
|
321
345
|
`ARTIFACTY_RETENTION_ALLOW_PURGE=true` in the server's environment. A
|
|
322
346
|
policy with purge candidates but no allow-purge gate set records them as
|
|
@@ -340,11 +364,8 @@ Controls:
|
|
|
340
364
|
## Out of Scope
|
|
341
365
|
|
|
342
366
|
- Public internet hosting without a separate TLS/auth proxy.
|
|
343
|
-
-
|
|
344
|
-
|
|
345
|
-
personal API token scopes described below.
|
|
346
|
-
- Group- or team-scoped ACLs beyond the single owner + team/private model
|
|
347
|
-
(see Artifact Visibility and Ownership above).
|
|
367
|
+
- OAuth. Personal API token scopes and direct or team artifact grants are
|
|
368
|
+
supported, as described above.
|
|
348
369
|
- Encrypted-at-rest storage.
|
|
349
370
|
- Malware analysis of arbitrary artifact content.
|
|
350
371
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Upgrade Snapshots and Recovery
|
|
2
|
+
|
|
3
|
+
Artifacty creates a local snapshot before it migrates an existing store to a newer schema. This snapshot is mandatory. If snapshot creation or verification fails, Artifacty stops before migration.
|
|
4
|
+
|
|
5
|
+
Use upgrade snapshots to recover the original store state. Use `artifacty backup` and `artifacty export` for portable JSON backups and store transfers. These are separate backup systems. `artifacty restore <id>` restores an archived artifact; it does not restore a store snapshot.
|
|
6
|
+
|
|
7
|
+
## When Artifacty Creates a Snapshot
|
|
8
|
+
|
|
9
|
+
- **Schema migration:** Artifacty always snapshots an existing store before migration. This includes a legacy `index.json` store. A new empty store needs no snapshot.
|
|
10
|
+
- **Application update:** Set `ARTIFACTY_BACKUP_ON_UPDATE=true` to also snapshot an existing store when the application version changes. This setting is off by default.
|
|
11
|
+
- **Unknown application version:** With the update setting enabled, the first open of an existing store without an application-version marker creates a baseline snapshot. Its source application version is unknown. Later opens with the same version do not repeat it.
|
|
12
|
+
- **Restore:** Before replacing a store, Artifacty creates and verifies a recovery snapshot of its current state.
|
|
13
|
+
|
|
14
|
+
Stop every HTTP server and MCP process that uses the store before an upgrade or restore. This includes services, foreground servers, and local stdio MCP clients. Artifacty checks managed server PID markers, but these markers cannot identify every process with an open store.
|
|
15
|
+
|
|
16
|
+
Snapshots are stored at `ARTIFACTY_HOME/upgrade-backups/<id>/`. The default home is `~/.artifacty`.
|
|
17
|
+
|
|
18
|
+
## Snapshot Contents
|
|
19
|
+
|
|
20
|
+
Each snapshot contains a manifest with file sizes and SHA-256 hashes. It also contains:
|
|
21
|
+
|
|
22
|
+
- A consistent raw SQLite database, including all tables and security state.
|
|
23
|
+
- Every version file referenced by the database or an authoritative legacy index.
|
|
24
|
+
- The legacy `index.json`, if it exists.
|
|
25
|
+
|
|
26
|
+
Verification checks the file hashes, SQLite integrity, and version-file references. Snapshots do not include unrelated files, process markers, logs, or the complete installation directory. Keep snapshots private: they contain credentials and security records.
|
|
27
|
+
|
|
28
|
+
`ARTIFACTY_UPGRADE_BACKUP_KEEP` controls automatic snapshot retention. The default is `3`; valid values are integers from `1` through `1000`. Artifacty prunes older automatic schema/update snapshots after a successful upgrade. It does not prune manual or recovery snapshots with this setting.
|
|
29
|
+
|
|
30
|
+
## Inspect Snapshots
|
|
31
|
+
|
|
32
|
+
List snapshots without opening or migrating the store:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
artifacty backups list --home /path/to/store
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Copy an `id` from the output. Verify that snapshot:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
artifacty backups verify <id> --home /path/to/store
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A successful response includes `valid: true`. Listing checks manifests; it does not replace full verification. From a repository checkout, use `node src/cli.js` in place of `artifacty`.
|
|
45
|
+
|
|
46
|
+
## Restore a Snapshot
|
|
47
|
+
|
|
48
|
+
A restore replaces the current database, version files, and legacy index. Changes made after the snapshot are no longer current. Artifacty keeps the pre-restore state in a separate recovery snapshot.
|
|
49
|
+
|
|
50
|
+
**Security state also rolls back.** Old passwords, permissions, network rules, sessions, API tokens, and share-link records can become current again. A session, token, or link revoked after the snapshot can become valid again if it has not expired. Review the restored security state before allowing users to reconnect.
|
|
51
|
+
|
|
52
|
+
1. Stop all server, service, and MCP processes that use this store.
|
|
53
|
+
2. Select a snapshot from `backups list`.
|
|
54
|
+
3. Verify it with `backups verify`.
|
|
55
|
+
4. Restore it with explicit confirmation:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
artifacty backups restore <id> --confirm restore-store --home /path/to/store
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
5. Save the returned `recoveryBackupId`.
|
|
62
|
+
6. Review the restored security settings before reconnecting clients.
|
|
63
|
+
|
|
64
|
+
Restore does not migrate the selected snapshot. Opening it with the current application can trigger another protected migration. A build that does not support the restored schema rejects the store.
|
|
65
|
+
|
|
66
|
+
## Recover When the Current Store Is Corrupt
|
|
67
|
+
|
|
68
|
+
If Artifacty cannot verify the current store for its recovery snapshot, it returns `RECOVERY_BACKUP_FAILED`. It does not overwrite the damaged store.
|
|
69
|
+
|
|
70
|
+
1. Keep the damaged home and its snapshots unchanged.
|
|
71
|
+
2. Create a new empty home directory.
|
|
72
|
+
3. Copy the selected snapshot directory into the new home's `upgrade-backups/` directory. Preserve its original snapshot ID and directory contents.
|
|
73
|
+
4. Run `backups verify <id> --home /path/to/new-home`.
|
|
74
|
+
5. Run `backups restore <id> --confirm restore-store --home /path/to/new-home`.
|
|
75
|
+
6. Review the restored data and security settings before using the new home.
|
|
76
|
+
|
|
77
|
+
Do not copy the damaged database over the new home. The selected snapshot supplies the database and referenced version files.
|
|
78
|
+
|
|
79
|
+
## Recover an Interrupted Restore
|
|
80
|
+
|
|
81
|
+
If a `.restore-<uuid>` directory remains, Artifacty stops with `RESTORE_INCOMPLETE`.
|
|
82
|
+
|
|
83
|
+
1. Preserve that directory and the entire affected home.
|
|
84
|
+
2. Read `.restore-<uuid>/restore.json`.
|
|
85
|
+
3. Find its `recoveryBackupId`. This identifies the snapshot of the state before the interrupted restore.
|
|
86
|
+
4. Copy that recovery snapshot into a new empty home's `upgrade-backups/` directory.
|
|
87
|
+
5. Verify and restore it there with the commands above.
|
|
88
|
+
|
|
89
|
+
Do not remove the interrupted restore directory to bypass the check. It contains recovery evidence and can contain the previous database and files.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Documentation writing style
|
|
2
|
+
|
|
3
|
+
Artifacty uses an ASD-STE100-inspired style for English documentation. Korean documentation follows the same clarity principles with natural Korean phrasing. This is an editorial guide, not a claim of compliance with ASD-STE100.
|
|
4
|
+
|
|
5
|
+
Apply the sentence and procedure rules consistently. Use technical vocabulary where it makes the meaning more precise. Keep introductions natural. The project's “75%” target describes this balance; it is not a compliance score.
|
|
6
|
+
|
|
7
|
+
## Sentences and terms
|
|
8
|
+
|
|
9
|
+
- Give each sentence one main idea. Split long sentences when this improves clarity.
|
|
10
|
+
- Name the actor when responsibility matters: the administrator, the artifact owner, the user, or the server.
|
|
11
|
+
- Prefer active voice. Use passive voice when the actor is unknown or does not matter.
|
|
12
|
+
- Use the same term for the same concept. Match UI labels, API fields, and CLI commands exactly.
|
|
13
|
+
- Keep established terms such as artifact, MCP, webhook, and CIDR. Explain unfamiliar terms on first use.
|
|
14
|
+
- Keep words that make a sentence complete. Do not turn prose into compressed notes.
|
|
15
|
+
- Do not enforce a fixed word limit or replace precise terms only to fit a controlled dictionary.
|
|
16
|
+
|
|
17
|
+
## Instructions and behavior
|
|
18
|
+
|
|
19
|
+
- State prerequisites and conditions before the action.
|
|
20
|
+
- Give each numbered step one action. Show the command or UI control that performs it.
|
|
21
|
+
- State the expected result when readers need it to verify the action.
|
|
22
|
+
- Make defaults, permissions, exceptions, and recovery behavior explicit.
|
|
23
|
+
- Keep requirements and recommendations distinct. Preserve the meaning of MUST, SHOULD, and MAY in specifications.
|
|
24
|
+
- Preserve commands, identifiers, URLs, examples, and technical constraints when editing prose.
|
|
25
|
+
- Describe planned features as planned. Do not present a design proposal as current behavior.
|
|
26
|
+
|
|
27
|
+
## Apply by document type
|
|
28
|
+
|
|
29
|
+
Use these rules most strictly in installation instructions, API references, and security documentation. Allow more connected prose in the README introduction, design rationale, and launch posts. Keep the explanation readers need; shorter text is not useful if it omits a condition or exception.
|
|
30
|
+
|
|
31
|
+
For example:
|
|
32
|
+
|
|
33
|
+
> By default, share links do not work in private mode. An administrator must enable them in Access settings.
|
|
34
|
+
|
|
35
|
+
This states the default, the responsible actor, and the setting location.
|
|
36
|
+
|
|
37
|
+
Refer to the [official ASD-STE100 overview](https://www.asd-ste100.org/about.html) for the specification's purpose and structure.
|
|
38
|
+
|
|
39
|
+
## 한국어 문서 작성 기준
|
|
40
|
+
|
|
41
|
+
한국어 문서에도 같은 명료성 원칙을 적용합니다. 다만 영어의 문장 구조나 어휘 규칙을 그대로 옮기지 않고, 자연스러운 한국어 어순과 흐름을 살립니다. ‘75% 강도’는 편집 방향을 뜻하며, 표준 준수율을 뜻하지 않습니다.
|
|
42
|
+
|
|
43
|
+
- 한 문장에는 하나의 핵심 내용을 담습니다. 서로 밀접한 내용은 자연스럽게 연결하고, 짧게 쓰기 위해 문장을 지나치게 끊지 않습니다.
|
|
44
|
+
- 조건이나 전제는 행동보다 먼저 설명합니다. 절차는 단계별로 나누고, 필요한 경우 예상 결과와 확인 방법을 덧붙입니다.
|
|
45
|
+
- 권한이나 책임을 구분해야 할 때는 주체를 밝힙니다. 문맥상 분명한 주어는 반복하지 않습니다.
|
|
46
|
+
- 번역투, 불필요한 수동 표현, 명사만 나열하는 문장을 피합니다. 예를 들어 ‘설정의 변경이 가능합니다’보다 ‘설정을 변경할 수 있습니다’로 씁니다.
|
|
47
|
+
- 같은 개념에는 같은 용어를 사용합니다. 화면 이름은 해당 언어의 실제 UI 표기와 맞추고, 명령어·API 필드·코드 식별자는 그대로 유지합니다.
|
|
48
|
+
- 익숙한 기술 용어는 억지로 번역하지 않습니다. 설명이 필요한 용어는 처음 나올 때 간단히 풀이합니다.
|
|
49
|
+
- 기본값, 예외, 제한, 복구 조건을 생략하지 않습니다. 필수 사항과 권장 사항도 명확히 구분합니다.
|
|
50
|
+
- 설명문은 ‘합니다’체를 기본으로 씁니다. 절차에서는 필요한 행동을 ‘선택하세요’, ‘실행하세요’처럼 직접 안내합니다.
|
|
51
|
+
|
|
52
|
+
예를 들어 다음과 같이 씁니다.
|
|
53
|
+
|
|
54
|
+
> 비공개 모드에서는 기본적으로 공유 링크를 사용할 수 없습니다. 관리자가 접근 설정에서 공유 링크를 허용해야 합니다.
|
|
55
|
+
|
|
56
|
+
설치·API·보안 문서에는 이 기준을 엄격하게 적용합니다. 소개 글과 설계 배경에서는 정확성을 유지하면서 문장이 자연스럽게 이어지도록 씁니다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artifacty",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Local artifact exchange for heterogeneous LLM agents via HTTP and MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"docs/roadmap-design.md",
|
|
45
45
|
"docs/sarif-csv-artifact-plan.md",
|
|
46
46
|
"docs/threat-model.md",
|
|
47
|
+
"docs/upgrade-backups.md",
|
|
48
|
+
"docs/writing-style.md",
|
|
47
49
|
"scripts/lint.mjs",
|
|
48
50
|
"scripts/smoke.sh",
|
|
49
51
|
"README.md",
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"CLAUDE.md"
|
|
55
57
|
],
|
|
56
58
|
"engines": {
|
|
57
|
-
"node": ">=22.
|
|
59
|
+
"node": ">=22.12"
|
|
58
60
|
},
|
|
59
61
|
"license": "MIT",
|
|
60
62
|
"dependencies": {
|
|
@@ -63,7 +65,7 @@
|
|
|
63
65
|
"@codemirror/lang-json": "^6.0.2",
|
|
64
66
|
"@codemirror/lang-markdown": "^6.5.0",
|
|
65
67
|
"codemirror": "^6.0.2",
|
|
66
|
-
"mermaid": "^
|
|
68
|
+
"mermaid": "^12.1.0"
|
|
67
69
|
},
|
|
68
70
|
"optionalDependencies": {
|
|
69
71
|
"@babel/standalone": "^8.0.4",
|