artifacty 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Artifacty
2
2
 
3
+ [![Publish](https://github.com/raeseoklee/artifacty/actions/workflows/publish.yml/badge.svg)](https://github.com/raeseoklee/artifacty/actions/workflows/publish.yml)
4
+ [![npm version](https://img.shields.io/npm/v/artifacty.svg)](https://www.npmjs.com/package/artifacty)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ [![Node.js >=22.5](https://img.shields.io/badge/node-%3E%3D22.5-339933.svg)](package.json)
7
+
3
8
  Artifacty is a local, agent-to-agent artifact exchange for LLM workflows. Claude, Codex, Gemini, and other MCP-capable tools can publish an artifact once, then other agents can list, read, update, and continue from it without copying content through chat.
4
9
 
5
10
  ![Artifacty overview showing multiple AI agents sharing artifacts through a local exchange](docs/assets/artifacty.png)
@@ -8,100 +13,183 @@ Artifacty is a local, agent-to-agent artifact exchange for LLM workflows. Claude
8
13
 
9
14
  Claude Code artifacts are useful because they turn session output into shareable, versioned pages. Artifacty keeps that local and cross-agent: the browser server renders artifacts for people, while the MCP stdio server gives agents a common tool interface.
10
15
 
11
- ## Quick Start
16
+ ## Installation
12
17
 
13
- Install and start Artifacty:
18
+ Artifacty requires Node.js 22.5 or newer.
19
+
20
+ Install the CLI globally from npm:
14
21
 
15
22
  ```bash
16
23
  npm install -g artifacty
17
- artifacty serve
24
+ artifacty --help
18
25
  ```
19
26
 
20
- For local development from a checkout:
27
+ Run it without a global install:
21
28
 
22
29
  ```bash
23
- npm install
24
- npm test
25
- npm start
30
+ npx artifacty@latest serve
31
+ ```
32
+
33
+ Start the local dashboard:
34
+
35
+ ```bash
36
+ artifacty serve
26
37
  ```
27
38
 
28
39
  Open the URL printed by the server. Artifacty prefers `http://127.0.0.1:8787`; if that default port is busy and no explicit port was configured, it starts on the next available local port and records the actual URL for CLI and MCP responses.
29
40
 
30
- Run the production-readiness check:
41
+ Generate an API token at startup when you want to protect HTTP API and browser write routes:
31
42
 
32
43
  ```bash
33
- npm run release:check
44
+ artifacty serve --generate-token
45
+ artifacty serve --host 0.0.0.0 --share-mode lan --generate-token
46
+ npm start -- --generate-token
34
47
  ```
35
48
 
49
+ The server prints the generated token plus `/new?token=...` and `/import?token=...` URLs. For scripts or background services that need a stable token, generate one first:
50
+
51
+ ```bash
52
+ artifacty token
53
+ ARTIFACTY_API_TOKEN="$(artifacty token --raw)" artifacty serve
54
+ ```
55
+
56
+ Install MCP configuration for local agents:
57
+
58
+ ```bash
59
+ artifacty install claude
60
+ artifacty install codex --dry-run
61
+ artifacty install gemini
62
+ artifacty install all
63
+ artifacty check
64
+ ```
65
+
66
+ Use `artifacty install codex --timeout 30000` or
67
+ `artifacty install gemini --timeout 30000` to tune supported MCP client timeouts.
68
+
69
+ See [docs/integrations.md](docs/integrations.md) for Claude Code, Codex, and Gemini CLI setup.
70
+
71
+ ## Quick Start
72
+
36
73
  Create an artifact in the browser:
37
74
 
38
75
  ```text
39
76
  http://127.0.0.1:8787/new
40
77
  ```
41
78
 
79
+ For local development from a checkout:
80
+
81
+ ```bash
82
+ npm install
83
+ npm test
84
+ npm start
85
+ ```
86
+
87
+ Run the production-readiness check:
88
+
89
+ ```bash
90
+ npm run release:check
91
+ ```
92
+
42
93
  Publish from the CLI:
43
94
 
44
95
  ```bash
45
- node src/cli.js publish --title "handoff note" --format markdown --source codex --content "# Next step\nReview the API plan."
96
+ artifacty publish --title "handoff note" --format markdown --source codex --content "# Next step\nReview the API plan."
46
97
  ```
47
98
 
48
99
  Import an artifact produced by another agent and convert it to Artifacty format:
49
100
 
50
101
  ```bash
51
- node src/cli.js import --agent claude --file ./deploy-failures.html --tag review
52
- node src/cli.js import --agent gemini --content '{"title":"Plan","returnDisplay":"# Plan\n- Ship it"}'
102
+ artifacty import --agent claude --file ./deploy-failures.html --tag review
103
+ artifacty import --agent gemini --content '{"title":"Plan","returnDisplay":"# Plan\n- Ship it"}'
104
+ artifacty import --agent codex --content '{"agent":"codex","title":"Implementation Handoff","goal":"Continue Phase 3","changedFiles":[{"path":"src/lib/render.js","status":"modified"}],"nextSteps":["Add CodeMirror read-only viewer"]}'
53
105
  ```
54
106
 
55
- List artifacts:
107
+ Codex structured payloads can become `handoff`, `bundle`, `diff-walkthrough`,
108
+ `code-review`, or `test-report` artifacts when the payload explicitly identifies
109
+ Codex through `agent` or `sourceAgent`. Plain Codex Markdown stays a normal
110
+ `document` unless you pass an explicit `artifactType`.
111
+
112
+ ## Agent Handoff Example
113
+
114
+ One agent can publish a continuation artifact, then another agent can discover it, read the context, and append the next version.
115
+
116
+ Codex publishes the handoff:
56
117
 
57
118
  ```bash
58
- node src/cli.js list
119
+ artifacty import --agent codex --tag handoff --content '{
120
+ "agent": "codex",
121
+ "title": "Release Handoff",
122
+ "goal": "Prepare Artifacty for an npm release",
123
+ "changedFiles": [
124
+ { "path": "src/lib/converters.js", "status": "modified", "summary": "Normalize agent outputs" }
125
+ ],
126
+ "commands": [
127
+ { "command": "npm run release:check", "status": "passed" }
128
+ ],
129
+ "nextSteps": [
130
+ "Review README",
131
+ "Publish package"
132
+ ]
133
+ }'
59
134
  ```
60
135
 
61
- Run the MCP server:
136
+ Claude or Gemini finds the handoff and continues from the same artifact:
62
137
 
63
138
  ```bash
64
- node src/mcp-server.js
139
+ artifacty list --tag handoff
140
+ artifacty show release-handoff-abc12345 --raw
141
+ artifacty update release-handoff-abc12345 \
142
+ --format markdown \
143
+ --source claude \
144
+ --tag handoff \
145
+ --content "# Release Handoff\n\nReviewed README and prepared publish notes."
65
146
  ```
66
147
 
67
- MCP clients can create artifacts with `artifacty_create`. `artifacty_publish` remains as a backwards-compatible alias.
148
+ List artifacts:
68
149
 
69
- Install MCP configuration for local agents:
150
+ ```bash
151
+ artifacty list
152
+ ```
153
+
154
+ Run the MCP server:
70
155
 
71
156
  ```bash
72
- node src/cli.js install claude
73
- node src/cli.js install codex --dry-run
74
- node src/cli.js install gemini
75
- node src/cli.js install all
76
- node src/cli.js check
157
+ artifacty-mcp
77
158
  ```
78
159
 
79
- See [docs/integrations.md](docs/integrations.md) for Claude Code, Codex, and Gemini CLI setup.
160
+ MCP clients can create artifacts with `artifacty_create`. `artifacty_publish` remains as a backwards-compatible alias.
80
161
 
81
162
  Operational commands:
82
163
 
83
164
  ```bash
84
- node src/cli.js audit --limit 20
85
- node src/cli.js backup
86
- node src/cli.js export --file ./artifacty-backup.json
87
- node src/cli.js import-store --file ./artifacty-backup.json
88
- node src/cli.js service install --dry-run
165
+ artifacty audit --limit 20
166
+ artifacty backup
167
+ artifacty export --file ./artifacty-backup.json
168
+ artifacty import-store --file ./artifacty-backup.json
169
+ artifacty service install --dry-run
89
170
  ```
90
171
 
91
- After global installation, the same commands are available as `artifacty` and `artifacty-mcp`.
172
+ When working from a source checkout without global installation, replace `artifacty` with `node src/cli.js` and `artifacty-mcp` with `node src/mcp-server.js`.
92
173
 
93
174
  ## Storage
94
175
 
95
176
  By default Artifacty stores files under `~/.artifacty`.
96
177
 
97
178
  ```bash
98
- ARTIFACTY_HOME=/path/to/shared/store npm start
179
+ ARTIFACTY_HOME=/path/to/shared/store artifacty serve
99
180
  ```
100
181
 
101
182
  Artifact metadata is stored in `artifacty.sqlite`; artifact content is stored as immutable version files under `artifacts/`. The current browser server URL is written to `server.json` so MCP tools can return the correct links when the default port falls back. Existing `index.json` stores are migrated automatically on first access.
102
183
 
103
184
  ## API Example
104
185
 
186
+ Start a protected server in another terminal, or generate a reusable shell token first:
187
+
188
+ ```bash
189
+ artifacty serve --generate-token
190
+ export ARTIFACTY_API_TOKEN="$(artifacty token --raw)"
191
+ ```
192
+
105
193
  ```bash
106
194
  curl -s http://127.0.0.1:8787/api/artifacts \
107
195
  -H 'content-type: application/json' \
@@ -134,7 +222,7 @@ Browser routes:
134
222
  - `/`: list artifacts with search, tag, and source filters.
135
223
  - `/new`: create an Artifacty-native artifact with the CodeMirror editor.
136
224
  - `/import`: paste an external agent artifact and convert it with automatic editor mode detection.
137
- - `/artifacts/:id/edit`: save a new version with Markdown, HTML, JSON, or text syntax support.
225
+ - `/artifacts/:id/edit`: save a new version with Markdown, HTML, JSON, text, code, SVG, Mermaid, or React syntax support.
138
226
  - `/artifacts/:id/diff`: compare versions.
139
227
  - `/api/audit`: list audit events.
140
228
 
@@ -147,18 +235,25 @@ Schema and storage:
147
235
  - Metadata lives in SQLite with `schemaVersion: 1`, `artifactType`, and `archivedAt`.
148
236
  - Archive hides artifacts from default lists without deleting versions.
149
237
  - Bundle artifacts store multiple files or base64 assets as portable JSON.
238
+ - Supported formats are `html`, `markdown`, `text`, `json`, `code`, `svg`, `mermaid`, and `react`.
239
+ - Diagram, component, and source snippet artifacts use `diagram`, `component`, and `snippet` artifact types.
150
240
  - See [docs/artifact-schema-v1.md](docs/artifact-schema-v1.md).
241
+ - See [docs/sarif-csv-artifact-plan.md](docs/sarif-csv-artifact-plan.md) for the SARIF/CSV output artifact roadmap.
151
242
 
152
243
  ## Security Model
153
244
 
154
245
  - The HTTP server binds to `127.0.0.1` by default.
155
246
  - If `ARTIFACTY_API_TOKEN` is set, HTTP API routes require `Authorization: Bearer <token>` or `x-artifacty-token`.
156
247
  - Binding outside localhost requires both `ARTIFACTY_SHARE_MODE=lan` or `team` and `ARTIFACTY_API_TOKEN`.
248
+ - Non-local sharing is intended for trusted LAN or VPN sessions. Prefer a specific interface IP over `0.0.0.0`, keep React rendering disabled, and see [docs/network-sharing.md](docs/network-sharing.md).
157
249
  - Artifact content is scanned for common API keys and private keys before storage. Use `--allow-secrets` or `ARTIFACTY_ALLOW_SECRETS=true` only for intentional exceptions.
158
250
  - Creates, updates, reads, imports, archives, and restores write audit events to SQLite.
159
- - CodeMirror editor assets are served from local npm dependencies through a package allowlist, not from a public CDN.
251
+ - CodeMirror editor/viewer and renderer assets are served from local npm dependencies through a package allowlist, not from a public CDN. JavaScript asset routes answer `Origin: null` requests with `Access-Control-Allow-Origin: null` so sandboxed renderer iframes can import local ESM without `allow-same-origin`.
160
252
  - Mutating HTTP routes reject non-local browser origins.
161
253
  - HTML artifacts render in a sandboxed iframe.
254
+ - SVG artifacts render in a scriptless sandboxed iframe and are sanitized for `<script>`, `on*` attributes, and `javascript:` links in the viewer. The raw source remains unchanged.
255
+ - Mermaid artifacts render with the vendored local Mermaid package in a sandboxed iframe without `allow-same-origin`.
256
+ - React artifacts are source-only by default. Set `ARTIFACTY_ENABLE_REACT_RENDERER=true` to execute them in a sandboxed frame with a frame-scoped CSP that permits JSX transformation.
162
257
  - Artifact content should still be treated as untrusted; use the raw view when handing content back to an agent.
163
258
 
164
259
  See [docs/release-checklist.md](docs/release-checklist.md) before publishing or running a shared instance.
@@ -32,6 +32,9 @@ Allowed `artifactType` values:
32
32
  - `diff-walkthrough`
33
33
  - `bundle`
34
34
  - `asset`
35
+ - `diagram`
36
+ - `component`
37
+ - `snippet`
35
38
  - `unknown`
36
39
 
37
40
  Unknown legacy or external types should be mapped to `unknown`, not rejected during conversion. Native create/update rejects unsupported explicit types.
@@ -53,7 +56,24 @@ Each version is immutable and points at one content file.
53
56
  }
54
57
  ```
55
58
 
56
- Allowed `format` values are `html`, `markdown`, `text`, and `json`.
59
+ Allowed `format` values are `html`, `markdown`, `text`, `json`, `code`, `svg`,
60
+ `mermaid`, and `react`.
61
+
62
+ ## Renderer Policy
63
+
64
+ Storage preserves artifact source as immutable content. Browser rendering is a
65
+ viewer concern and must treat all source as untrusted:
66
+
67
+ - `code`: read-only CodeMirror viewer with escaped source fallback.
68
+ - `svg`: scriptless sandboxed iframe after viewer-side sanitization; `/raw`
69
+ preserves the original source.
70
+ - `mermaid`: vendored local Mermaid bundle in a sandboxed iframe without
71
+ `allow-same-origin`. Local JavaScript assets use
72
+ `Access-Control-Allow-Origin: null` for `Origin: null` requests so the
73
+ opaque-origin frame can import ESM.
74
+ - `react`: source-only by default. `ARTIFACTY_ENABLE_REACT_RENDERER=true`
75
+ enables a separate sandboxed frame with frame-scoped CSP for JSX transform and
76
+ execution.
57
77
 
58
78
  ## Metadata
59
79
 
@@ -63,6 +83,11 @@ Metadata is free-form JSON, but converter-generated metadata uses these keys:
63
83
  - `originalPayloadShape`: original payload family, such as `gemini-llmContent`, `content`, or `artifact-bundle`.
64
84
  - `assetPolicy`: how embedded assets were preserved.
65
85
  - `bundlePolicy`: how bundled files were preserved.
86
+ - `language`: source language for code or component artifacts when supplied by an
87
+ upstream agent.
88
+ - `codexContinuation`: structured Codex handoff metadata such as changed files,
89
+ commands, tests, blockers, decisions, next steps, findings, diff text, and
90
+ residual risk.
66
91
 
67
92
  ## Archive Semantics
68
93
 
@@ -10,9 +10,21 @@ npm start
10
10
 
11
11
  The dashboard prefers `http://127.0.0.1:8787`. If that port is busy and no explicit port is configured, the server starts on the next available local port and records the actual URL in the store. The store defaults to `~/.artifacty`; set `ARTIFACTY_HOME` to share a different local directory.
12
12
 
13
+ Use a generated startup token when running a protected foreground server:
14
+
15
+ ```bash
16
+ node src/cli.js serve --generate-token
17
+ node src/cli.js serve --host 0.0.0.0 --share-mode lan --generate-token
18
+ npm start -- --generate-token
19
+ ```
20
+
21
+ The generated token is printed with ready-to-open create and import URLs.
22
+
13
23
  Create artifacts directly in the browser at `http://127.0.0.1:8787/new`.
14
24
 
15
- The browser create/import/edit screens use CodeMirror 6 for Markdown, HTML, JSON, and plain text editing. Editor assets are served from local npm dependencies through `/assets/editor.js` and allowlisted `/vendor/npm/*` module routes.
25
+ For LAN or VPN sharing, keep the default local binding unless you intentionally need another machine to reach the server. See [network-sharing.md](network-sharing.md) before using `--host 0.0.0.0`.
26
+
27
+ The browser create/import/edit screens use CodeMirror 6 for Markdown, HTML, JSON, source-like text, SVG, Mermaid, and React artifact editing. Editor and renderer assets are served from local npm dependencies through `/assets/*.js` and allowlisted `/vendor/npm/*` module routes. For sandboxed iframe imports, `Origin: null` requests receive `Access-Control-Allow-Origin: null`, which lets opaque-origin iframes import local ESM without `allow-same-origin`.
16
28
 
17
29
  The browser UI defaults to English. Add `?lang=ko` to browser routes to use Korean UI labels; API and MCP payloads are not localized.
18
30
 
@@ -28,7 +40,7 @@ Useful environment variables:
28
40
 
29
41
  - `ARTIFACTY_HOME`: store directory, shared by all agents.
30
42
  - `ARTIFACTY_URL`: optional browser URL override. Leave it unset to let MCP read the last running server URL from `server.json`.
31
- - `ARTIFACTY_API_TOKEN`: required token for HTTP API routes when configured.
43
+ - `ARTIFACTY_API_TOKEN`: required token for HTTP API routes when configured. Generate one with `node src/cli.js token --raw`.
32
44
  - `ARTIFACTY_SHARE_MODE`: set to `lan` or `team` before binding outside localhost.
33
45
  - `ARTIFACTY_ALLOW_SECRETS`: set to `true` only when intentionally storing detected secrets.
34
46
 
@@ -44,12 +56,22 @@ node src/cli.js install all
44
56
  node src/cli.js check
45
57
  ```
46
58
 
47
- - Claude: writes project `.mcp.json`.
48
- - Codex: writes or replaces the `[mcp_servers.artifacty]` block in `~/.codex/config.toml` unless `--config` is provided.
49
- - Gemini: writes project `.gemini/settings.json`.
59
+ - Claude: writes project `.mcp.json`. Claude Code's startup timeout is controlled by the parent `MCP_TIMEOUT` environment variable and defaults to 30 seconds, so Artifacty does not add a per-server `.mcp.json` `timeout` field.
60
+ - Codex: writes or replaces the `[mcp_servers.artifacty]` block in `~/.codex/config.toml` unless `--config` is provided. The generated block uses a 30 second startup timeout so slower Windows or cold-start environments can load the MCP server reliably.
61
+ - Gemini: writes project `.gemini/settings.json` with a 30 second timeout.
50
62
  - `--dry-run` returns the generated config without writing it.
63
+ - `--timeout <ms>` adjusts Codex `startup_timeout_sec` and Gemini `timeout`. It does not change Claude Code startup behavior; set `MCP_TIMEOUT` before launching Claude Code if you need a larger value there.
51
64
  - `check` starts the local MCP server and verifies required tools through `initialize` and `tools/list`.
52
65
 
66
+ Generate a token for protected HTTP routes:
67
+
68
+ ```bash
69
+ node src/cli.js token
70
+ node src/cli.js serve --generate-token
71
+ npm start -- --generate-token
72
+ ARTIFACTY_API_TOKEN="$(node src/cli.js token --raw)" node src/cli.js serve
73
+ ```
74
+
53
75
  ## Claude Code
54
76
 
55
77
  Manual local stdio MCP server:
@@ -76,6 +98,11 @@ Project-scoped `.mcp.json` shape:
76
98
 
77
99
  Claude plugins can bundle MCP servers, so this MCP server can later be wrapped as a plugin. The MVP keeps the server standalone so Claude, Codex, Gemini, and other MCP clients use the same integration surface.
78
100
 
101
+ Claude Code uses a 30 second MCP startup timeout by default. If a slower
102
+ environment needs more time, launch Claude Code with a larger `MCP_TIMEOUT`
103
+ value, for example `MCP_TIMEOUT=45000 claude`. Do not add a `.mcp.json`
104
+ `timeout` field for startup; that field is for tool execution timeout.
105
+
79
106
  ## Codex
80
107
 
81
108
  Add a local MCP server entry to the Codex config:
@@ -84,12 +111,32 @@ Add a local MCP server entry to the Codex config:
84
111
  [mcp_servers.artifacty]
85
112
  command = "node"
86
113
  args = ["/path/to/artifacty/src/mcp-server.js"]
87
- startup_timeout_sec = 5.0
114
+ startup_timeout_sec = 30.0
88
115
  env = { ARTIFACTY_HOME = "/absolute/path/to/artifacty-store" }
89
116
  ```
90
117
 
91
118
  Restart the Codex session after editing config so the MCP server is loaded.
92
119
 
120
+ Codex can publish continuation artifacts directly through MCP. Prefer explicit
121
+ `sourceAgent: "codex"` and an `artifactType` when the content is already
122
+ Markdown:
123
+
124
+ ```json
125
+ {
126
+ "title": "Implementation Handoff",
127
+ "content": "# Handoff\n\n- Continue Phase 3.",
128
+ "format": "markdown",
129
+ "artifactType": "handoff",
130
+ "sourceAgent": "codex",
131
+ "tags": ["handoff"]
132
+ }
133
+ ```
134
+
135
+ For structured continuation payloads, use `artifacty_import` with `agent:
136
+ "codex"`. Artifacty converts handoffs, file bundles, diff walkthroughs, code
137
+ reviews, and verification reports into the shared schema while preserving
138
+ changed files, commands, tests, blockers, and next steps in metadata.
139
+
93
140
  ## Gemini CLI
94
141
 
95
142
  Add a server to `~/.gemini/settings.json` or `.gemini/settings.json`:
@@ -134,13 +181,14 @@ Use `artifacty_import` or the CLI `import` command when the artifact was produce
134
181
  ```bash
135
182
  node src/cli.js import --agent claude --file ./artifact.html --tag review
136
183
  node src/cli.js import --agent codex --file ./handoff.md --tag handoff
184
+ node src/cli.js import --agent codex --content '{"agent":"codex","title":"Verification","verification":{"status":"passed","commands":[{"command":"npm test","status":"passed"}]}}'
137
185
  node src/cli.js import --agent gemini --content '{"title":"Options","returnDisplay":"# Options\n- A\n- B"}'
138
186
  ```
139
187
 
140
188
  Supported converter inputs:
141
189
 
142
- - Claude: local `.html`, `.htm`, `.md`, or JSON payloads with `title`/`content`.
143
- - Codex: markdown/text/json handoff files, or JSON payloads with `title`, `content`, `format`, `sourceAgent`, and `tags`.
190
+ - Claude: local `.html`, `.htm`, `.md`, `.svg`, `.mmd`, `.jsx`, `.tsx`, source files, or JSON payloads with `title`/`content`/Claude artifact `type`.
191
+ - Codex: markdown/text/json handoff files; Artifacty-compatible JSON payloads; structured handoff, bundle, diff, review, and verification JSON payloads with `agent` or `sourceAgent` set to `codex`.
144
192
  - Gemini: `returnDisplay`, `llmContent`, text blocks, or local markdown/text/json files.
145
193
  - Generic: file extension, content type, HTML doctype, JSON shape, and markdown headings are used to infer format and title.
146
194
 
@@ -163,6 +211,7 @@ The converter adds `imported` and source-agent tags, preserves the raw content a
163
211
  - `POST /api/artifacts/:id/restore`: restore an archived artifact.
164
212
  - `GET /api/audit`: list recent audit events, optionally filtered by `artifactId`.
165
213
  - `GET /artifacts/:id`: browser viewer.
214
+ - `GET /artifacts/:id/react-frame?version=n`: gated React renderer frame. Returns content only when `ARTIFACTY_ENABLE_REACT_RENDERER=true`.
166
215
  - `GET /artifacts/:id/edit`: browser version editor.
167
216
  - `POST /artifacts/:id/edit`: append a version from the browser editor.
168
217
  - `POST /artifacts/:id/archive`: archive from the browser.
@@ -172,6 +221,13 @@ The converter adds `imported` and source-agent tags, preserves the raw content a
172
221
 
173
222
  When `ARTIFACTY_API_TOKEN` is configured, `/api/*` routes require either `Authorization: Bearer <token>` or `x-artifacty-token: <token>`. Browser forms can also carry `?token=<token>` in the URL, which is copied to hidden form fields for local team workflows.
174
223
 
224
+ Renderer notes:
225
+
226
+ - `code` artifacts use a read-only CodeMirror viewer with escaped source fallback.
227
+ - `svg` artifacts render in a scriptless sandboxed iframe after viewer-side sanitization; `/raw` still returns the original SVG.
228
+ - `mermaid` artifacts load the vendored local Mermaid bundle from `/vendor/npm/mermaid/...` in a sandboxed iframe without `allow-same-origin`. The JavaScript asset route answers the iframe's `Origin: null` module request with `Access-Control-Allow-Origin: null`.
229
+ - `react` artifacts are source-only unless `ARTIFACTY_ENABLE_REACT_RENDERER=true` is set. When enabled, JSX transformation and React execution happen only in `/artifacts/:id/react-frame`, with `unsafe-eval` scoped to that frame CSP.
230
+
175
231
  ## Background Service
176
232
 
177
233
  Generate or install a macOS LaunchAgent plist:
@@ -184,6 +240,8 @@ node src/cli.js service install
184
240
 
185
241
  The generated service runs `src/server.js` with explicit `--host` and `--home` arguments. It includes `--port` only when you configure a port, which keeps the default port fallback available. Load or unload it manually with the `launchctl` commands returned by `service install`.
186
242
 
243
+ For background services, prefer a stable `ARTIFACTY_API_TOKEN` in the service environment. `serve --generate-token` is intended for foreground runs where the operator can read the generated token from startup output.
244
+
187
245
  ## Backup and Audit
188
246
 
189
247
  ```bash
@@ -0,0 +1,41 @@
1
+ # Network Sharing
2
+
3
+ Artifacty is local-first. The default server binds to `127.0.0.1` and is intended for a single machine. Binding to a non-local address is supported for short, intentional sharing sessions, but it increases the exposed surface area.
4
+
5
+ ## Recommended Defaults
6
+
7
+ Use the local server for normal work:
8
+
9
+ ```bash
10
+ artifacty serve
11
+ ```
12
+
13
+ If another device on a trusted LAN or private VPN needs read access, prefer binding to a specific interface address instead of every interface:
14
+
15
+ ```bash
16
+ artifacty serve --host 192.168.1.20 --share-mode lan --generate-token
17
+ ```
18
+
19
+ Use `0.0.0.0` only when you intentionally want Artifacty to listen on every network interface:
20
+
21
+ ```bash
22
+ artifacty serve --host 0.0.0.0 --share-mode lan --generate-token
23
+ ```
24
+
25
+ ## Required Safeguards
26
+
27
+ Non-local hosts require both `ARTIFACTY_SHARE_MODE=lan|team` and an API token. This prevents accidentally exposing an unauthenticated Artifacty server.
28
+
29
+ The generated token protects HTTP API routes and browser write forms. Prefer the `x-artifacty-token` or `Authorization: Bearer <token>` header for scripts. URLs with `?token=...` are convenient for local foreground sessions, but can be stored in browser history, shell history, reverse-proxy logs, or referrers.
30
+
31
+ Artifacty does not terminate TLS. Do not expose it directly on the public internet. If a shared instance must cross an untrusted network, put it behind a TLS reverse proxy or a private VPN.
32
+
33
+ ## Browser Write Behavior
34
+
35
+ Remote browsers can read shared pages, but write actions are intentionally conservative. Mutating browser routes reject non-local `Origin` headers to reduce CSRF risk. For LAN sharing, prefer API or MCP writes with an explicit token header.
36
+
37
+ Do not relax the origin check just to make remote browser writes easier. A future team dashboard should use a dedicated policy that combines same-origin remote requests, explicit token validation, and clear operator intent.
38
+
39
+ ## Renderer Guidance
40
+
41
+ Artifact content is untrusted. HTML, SVG, Mermaid, and React artifacts are rendered with sandboxing and CSP controls, but shared viewing still means content reaches another user's browser. Keep `ARTIFACTY_ENABLE_REACT_RENDERER` disabled for LAN sessions unless every viewer trusts the artifact source.
@@ -14,6 +14,9 @@ This runs syntax checks, the full Node test suite, and a local smoke test that s
14
14
 
15
15
  - Confirm `package.json` `version` and `files` are intentional.
16
16
  - Run `npm pack --dry-run` and inspect the included paths.
17
+ - Review package size after renderer dependencies. Mermaid is a default dependency;
18
+ React, ReactDOM, and Babel standalone are optional dependencies used only by the
19
+ gated React renderer.
17
20
  - Verify the global commands resolve after install: `artifacty`, `artifacty-mcp`.
18
21
 
19
22
  ## Security
@@ -22,6 +25,16 @@ This runs syntax checks, the full Node test suite, and a local smoke test that s
22
25
  - Require `ARTIFACTY_API_TOKEN` and `ARTIFACTY_SHARE_MODE=lan` or `team` before binding to `0.0.0.0`.
23
26
  - Review secret-scan bypasses. `--allow-secrets` and `ARTIFACTY_ALLOW_SECRETS=true` should be deliberate and temporary.
24
27
  - Treat artifact HTML and imported agent payloads as untrusted content.
28
+ - Confirm scripted artifact iframes never include `allow-same-origin`.
29
+ - Confirm `/assets/*` and `/vendor/npm/*` JavaScript responses return
30
+ `Access-Control-Allow-Origin: null` only for `Origin: null` requests, so
31
+ opaque-origin sandbox iframes can import local ESM without weakening sandbox
32
+ flags or using a wildcard CORS policy.
33
+ - Confirm SVG viewer output strips `<script>`, `on*` attributes, and `javascript:` links while `/raw` preserves original source.
34
+ - Browser-smoke each renderer that executes client code. Route status alone does
35
+ not prove Mermaid or React rendered inside the iframe.
36
+ - Keep `ARTIFACTY_ENABLE_REACT_RENDERER` disabled by default. Enable it only when the operator accepts arbitrary component execution risk.
37
+ - Confirm parent app CSP does not include `unsafe-eval`; it should appear only on the React frame response CSP.
25
38
 
26
39
  ## Operations
27
40
 
@@ -0,0 +1,65 @@
1
+ # SARIF and CSV Artifact Support Plan
2
+
3
+ This plan scopes SARIF and CSV support to **output artifacts** that Codex or
4
+ other agents generate for downstream review. It does not cover Codex input
5
+ context, appshots, thread state, or client-specific UI state.
6
+
7
+ ## Goals
8
+
9
+ - Preserve SARIF and CSV files as immutable Artifacty versions.
10
+ - Classify common Codex Security exports without requiring manual
11
+ `artifactType` overrides.
12
+ - Render CSV outputs in a readable table view while keeping `/raw` unchanged.
13
+ - Keep SARIF as JSON-first, with future room for a findings-focused viewer.
14
+
15
+ ## Current Behavior
16
+
17
+ - `.sarif` content is stored as `json` when the payload is valid JSON, but it
18
+ currently falls back to `artifactType: "unknown"`.
19
+ - `.csv` and `text/csv` content can be stored as `text`, but there is no CSV
20
+ detection, table renderer, or artifact-type inference.
21
+ - Security findings exported as JSON, CSV, or SARIF can be shared today, but the
22
+ browsing experience is not yet tailored to review workflows.
23
+
24
+ ## Phase 1: Detection and Taxonomy
25
+
26
+ - Detect `.sarif` and `application/sarif+json` as `json`.
27
+ - Detect SARIF shape (`version`, `runs[]`, `tool.driver`) and classify as
28
+ `code-review`.
29
+ - Detect `.csv` and `text/csv` as either a new `csv` format or `text` with
30
+ `metadata.delimitedText`.
31
+ - Infer `code-review` for CSV/SARIF files named like `findings`, `security`,
32
+ `review`, or containing columns such as `severity`, `file`, and `message`.
33
+
34
+ Exit criteria: CLI, HTTP, and MCP imports classify SARIF and common findings CSV
35
+ without explicit overrides.
36
+
37
+ ## Phase 2: CSV Viewer
38
+
39
+ - Add a lightweight RFC 4180-style CSV parser for browser rendering.
40
+ - Render CSV as a scrollable table with sticky headers and escaped cell content.
41
+ - Cap rendered rows and columns for very large files, with a visible truncation
42
+ notice and a link to `/raw`.
43
+ - Preserve plain text fallback when parsing fails.
44
+
45
+ Exit criteria: CSV artifacts are readable in the browser and raw fidelity is
46
+ unchanged.
47
+
48
+ ## Phase 3: SARIF Summary Viewer
49
+
50
+ - Keep SARIF source as JSON.
51
+ - Add an optional summary above the JSON view: rule id, severity/level, message,
52
+ file URI, region, and result count by level.
53
+ - Avoid implementing the complete SARIF spec in v1; parse only stable top-level
54
+ fields and fail closed to JSON rendering.
55
+
56
+ Exit criteria: SARIF exports are useful for quick triage while preserving the
57
+ full JSON source.
58
+
59
+ ## Tests
60
+
61
+ - Converter fixtures: Codex Security SARIF, findings CSV, generic CSV, malformed
62
+ CSV, and large CSV.
63
+ - Storage round trips: content type, extension, size, hash, and `/raw` fidelity.
64
+ - Server rendering: CSV table escaping, truncation notice, SARIF summary fallback.
65
+ - MCP schema and import tests for explicit and inferred artifact types.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artifacty",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Local artifact exchange for heterogeneous LLM agents via HTTP and MCP.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -34,7 +34,12 @@
34
34
  },
35
35
  "files": [
36
36
  "src",
37
- "docs",
37
+ "docs/artifact-schema-v1.md",
38
+ "docs/assets/artifacty.png",
39
+ "docs/integrations.md",
40
+ "docs/network-sharing.md",
41
+ "docs/release-checklist.md",
42
+ "docs/sarif-csv-artifact-plan.md",
38
43
  "scripts/smoke.sh",
39
44
  "README.md",
40
45
  "LICENSE",
@@ -48,8 +53,15 @@
48
53
  "license": "MIT",
49
54
  "dependencies": {
50
55
  "@codemirror/lang-html": "^6.4.11",
56
+ "@codemirror/lang-javascript": "^6.2.5",
51
57
  "@codemirror/lang-json": "^6.0.2",
52
58
  "@codemirror/lang-markdown": "^6.5.0",
53
- "codemirror": "^6.0.2"
59
+ "codemirror": "^6.0.2",
60
+ "mermaid": "^11.15.0"
61
+ },
62
+ "optionalDependencies": {
63
+ "@babel/standalone": "^7.29.7",
64
+ "react": "^18.3.1",
65
+ "react-dom": "^18.3.1"
54
66
  }
55
67
  }
package/scripts/smoke.sh CHANGED
@@ -74,6 +74,7 @@ assert(response.status === 201, `expected create status 201, got ${response.stat
74
74
  const created = await response.json();
75
75
  assert(created.id && created.rawUrl, "create response missing artifact URLs");
76
76
 
77
+ const fakeGithubToken = ["ghp", "abcdefghijklmnopqrstuvwxyz123456"].join("_");
77
78
  response = await fetch(`${url}/api/artifacts`, {
78
79
  method: "POST",
79
80
  headers: {
@@ -82,7 +83,7 @@ response = await fetch(`${url}/api/artifacts`, {
82
83
  },
83
84
  body: JSON.stringify({
84
85
  title: "Blocked Secret",
85
- content: "ghp_abcdefghijklmnopqrstuvwxyz123456",
86
+ content: fakeGithubToken,
86
87
  format: "text"
87
88
  })
88
89
  });