@event4u/agent-config 4.1.0 → 4.2.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.
Files changed (60) hide show
  1. package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/CHANGELOG.md +35 -0
  4. package/README.md +3 -2
  5. package/dist/discovery/deprecation-report.md +1 -1
  6. package/dist/discovery/discovery-manifest.json +1 -1
  7. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  8. package/dist/discovery/discovery-manifest.summary.md +1 -1
  9. package/dist/discovery/orphan-report.md +1 -1
  10. package/dist/discovery/packs.json +1 -1
  11. package/dist/discovery/trust-report.md +1 -1
  12. package/dist/discovery/workspaces.json +1 -1
  13. package/dist/mcp/registry-manifest.json +1 -1
  14. package/dist/server/routes/install.js +11 -200
  15. package/dist/server/routes/install.js.map +1 -1
  16. package/dist/server/routes/wizard.js +167 -26
  17. package/dist/server/routes/wizard.js.map +1 -1
  18. package/dist/server/schemas/settings.js +1 -0
  19. package/dist/server/schemas/settings.js.map +1 -1
  20. package/dist/ui/assets/index-BDAhhpDV.js +40 -0
  21. package/dist/ui/assets/index-BDAhhpDV.js.map +1 -0
  22. package/dist/ui/index.html +1 -1
  23. package/docs/contracts/gui-wizard.md +109 -96
  24. package/docs/decisions/ADR-021-deployment-shape.md +2 -2
  25. package/docs/deploy/connector-setup.md +2 -2
  26. package/docs/deploy/policy-cookbook.md +2 -2
  27. package/package.json +1 -1
  28. package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  29. package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  30. package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  31. package/scripts/install.py +197 -34
  32. package/scripts/lint_framework_leakage_allowlist.json +8 -0
  33. package/dist/install/apply.js +0 -238
  34. package/dist/install/apply.js.map +0 -1
  35. package/dist/install/bridges/augment.js +0 -20
  36. package/dist/install/bridges/augment.js.map +0 -1
  37. package/dist/install/bridges/claude.js +0 -44
  38. package/dist/install/bridges/claude.js.map +0 -1
  39. package/dist/install/bridges/cline.js +0 -69
  40. package/dist/install/bridges/cline.js.map +0 -1
  41. package/dist/install/bridges/copilot.js +0 -28
  42. package/dist/install/bridges/copilot.js.map +0 -1
  43. package/dist/install/bridges/cursor.js +0 -34
  44. package/dist/install/bridges/cursor.js.map +0 -1
  45. package/dist/install/bridges/gemini.js +0 -39
  46. package/dist/install/bridges/gemini.js.map +0 -1
  47. package/dist/install/bridges/index.js +0 -88
  48. package/dist/install/bridges/index.js.map +0 -1
  49. package/dist/install/bridges/marker-content.js +0 -153
  50. package/dist/install/bridges/marker-content.js.map +0 -1
  51. package/dist/install/bridges/markers.js +0 -42
  52. package/dist/install/bridges/markers.js.map +0 -1
  53. package/dist/install/bridges/types.js +0 -31
  54. package/dist/install/bridges/types.js.map +0 -1
  55. package/dist/install/bridges/vscode.js +0 -26
  56. package/dist/install/bridges/vscode.js.map +0 -1
  57. package/dist/install/bridges/windsurf.js +0 -35
  58. package/dist/install/bridges/windsurf.js.map +0 -1
  59. package/dist/ui/assets/index-DLEuEW1V.js +0 -35
  60. package/dist/ui/assets/index-DLEuEW1V.js.map +0 -1
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <meta name="robots" content="noindex" />
7
7
  <title>agent-config</title>
8
- <script type="module" crossorigin src="/assets/index-DLEuEW1V.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-BDAhhpDV.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-BXZILUxe.css">
10
10
  </head>
11
11
  <body>
@@ -8,20 +8,27 @@ keep-beta-until: 2026-08-19
8
8
  > Companion to the agent-mode protocol
9
9
  > ([`installer-agent-mode.md`](installer-agent-mode.md)) and the
10
10
  > trust-and-safety layer ([`trust-and-safety.md`](trust-and-safety.md)).
11
- > The wizard is a thin HTTP wrapper around the same install plan, the
12
- > same lockfile, and the same atomic-write semantics as the CLI/TUI
13
- > paths. It is **optional by design** — the CLI is the canonical entry
14
- > point; the wizard exists for non-technical users who want a visual
15
- > picker.
11
+ > The wizard is a thin HTTP wrapper: it is a **selection front-end**, and
12
+ > every real write goes through the single installer
13
+ > `scripts/install.py --apply-payload` (D12 / ADR-020). It is **optional by
14
+ > design** the CLI is the canonical entry point; the wizard exists for
15
+ > non-technical users who want a visual picker.
16
16
 
17
17
  ## Source of truth
18
18
 
19
- - Server: [`packages/core/installer/src/gui/server.ts`](../../packages/core/installer/src/gui/server.ts)
20
- - Handlers: [`packages/core/installer/src/gui/handlers.ts`](../../packages/core/installer/src/gui/handlers.ts)
21
- - Security primitives: [`packages/core/installer/src/gui/security.ts`](../../packages/core/installer/src/gui/security.ts)
22
- - Inlined SPA: [`packages/core/installer/src/gui/static-assets.ts`](../../packages/core/installer/src/gui/static-assets.ts)
23
- - Transaction log: [`packages/core/installer/src/gui/transaction-log.ts`](../../packages/core/installer/src/gui/transaction-log.ts)
24
- - Tests: [`packages/core/installer/tests/gui-*.test.ts`](../../packages/core/installer/tests/)
19
+ The GUI is a Fastify server (`src/server/`) serving a Preact SPA
20
+ (`src/ui/`), booted by the `install` / `setup` / `ui:serve` CLI
21
+ subcommands. The legacy `packages/core/installer/src/gui/*` tree was
22
+ retired; the single real installer is `scripts/install.py`.
23
+
24
+ - Server app + security hooks: [`src/server/app.ts`](../../src/server/app.ts) (Host allow-list, Origin allow-list, CSRF token — `onRequest` hooks)
25
+ - Wizard routes (incl. the real-apply bridge): [`src/server/routes/wizard.ts`](../../src/server/routes/wizard.ts)
26
+ - Read-only install routes (detect / plan-preview / recovery / legacy-v3): [`src/server/routes/install.ts`](../../src/server/routes/install.ts)
27
+ - Atomic / 2PC writes: [`src/server/io/atomicWrite.ts`](../../src/server/io/atomicWrite.ts), [`atomicMultiWrite.ts`](../../src/server/io/atomicMultiWrite.ts)
28
+ - SPA: [`src/ui/`](../../src/ui/) (entry `src/ui/pages/WizardPage.tsx`)
29
+ - CLI boot + `WIZARD_READY` contract: [`src/cli/commands/uiServe.ts`](../../src/cli/commands/uiServe.ts)
30
+ - The single installer (all real writes): [`scripts/install.py`](../../scripts/install.py)
31
+ - Tests: [`tests/server/`](../../tests/server/) + [`tests/e2e/`](../../tests/e2e/)
25
32
 
26
33
  ## Local-only invariant
27
34
 
@@ -34,106 +41,111 @@ no cross-origin asset, no remote endpoint — CSP
34
41
  ## Boot sequence
35
42
 
36
43
  ```
37
- npx @event4u/agent-config init --gui [--gui-port=<n>] [--no-open] [--gui-idle=<s>]
44
+ agent-config install (or `setup`, or `init` scripts/install.py spawns
45
+ `node dist/cli/agent-config.js install --no-open`)
38
46
 
39
- ├─► inspect agents/runtime/gui/server.pid abort if live
40
- ├─► load dist/discovery/discovery-manifest.json (walks up from CWD)
41
- ├─► generate per-server CSRF token (64-hex)
42
- ├─► http.createServer + listen({ host: '127.0.0.1', port: 0 })
43
- ├─► write agents/runtime/gui/server.pid (POSIX pid, single line)
44
- ├─► default-spawn the OS browser opener (skipped with --no-open)
45
- └─► return GuiServerHandle { url, port, csrfToken, pidFile, close }
47
+ ├─► pick a free loopback port; mint a per-server bearer/CSRF token
48
+ ├─► Fastify listen({ host: '127.0.0.1', port })
49
+ ├─► print `WIZARD_READY <url>` on stdout (url carries `?token=…` + `#/…`)
50
+ ├─► open the OS browser at <url> (skipped with --no-open / headless)
51
+ └─► serve until Ctrl-C
46
52
  ```
47
53
 
48
- Idle timeout (default 600 s, configurable via `--gui-idle`) is keyed on
49
- the **last HTTP request timestamp**, not on SSE event activity.
54
+ `init` is the consumer entry point: it delegates to `scripts/install.py`,
55
+ which on a TTY with a display and no `--no-ui` / `CI` / explicit
56
+ `--tools=` — spawns the `install` subcommand with `--no-open` and waits for
57
+ the `WIZARD_READY <url>` handshake (progressive 10/20/40/80 s budget) before
58
+ printing the URL banner. Headless / CI / `--no-ui` / explicit `--tools=`
59
+ installs run the non-interactive `install.py` path directly and never boot
60
+ the GUI.
61
+
62
+ ### `WIZARD_READY` stdout contract
63
+
64
+ The server emits exactly one line on stdout when it has bound:
65
+
66
+ ```
67
+ WIZARD_READY http://127.0.0.1:<port>/?token=<token>#/<route>
68
+ ```
69
+
70
+ The supervisor matches `^WIZARD_READY (http://(127.0.0.1|localhost):\d+/\S*)$`
71
+ (no `url=` prefix; the query/hash are part of the captured URL). The line is
72
+ unconditional so headless CI can detect "Fastify bound" without polling the
73
+ port.
50
74
 
51
75
  ## Endpoints
52
76
 
53
- | Method | Path | Purpose |
54
- |--------|------------------|------------------------------------------------------|
55
- | GET | `/` | SPA shell with CSRF token injected via `<meta>` |
56
- | GET | `/app.css` | Static stylesheet |
57
- | GET | `/app.js` | Inlined SPA logic |
58
- | GET | `/api/manifest` | `{ manifest, sha256 }` — bytes-identical to disk |
59
- | GET | `/api/auto-detect` | `{ signals: { composer, package, pyproject } }` |
60
- | POST | `/api/preview` | `{ plan, lockfileSha256 }` for current selection |
61
- | POST | `/api/apply` | SSE: `plan-file`, `progress`, `done`, `error` |
62
- | POST | `/api/cancel` | Flush in-flight transaction log, close SSE stream |
63
-
64
- All POSTs require:
65
-
66
- 1. `Origin` header matching `http://127.0.0.1:<port>` or
67
- `http://localhost:<port>`.
68
- 2. Body field `csrf` matching the per-server token (timing-safe
69
- compare in `security.ts`).
70
-
71
- A bad CSRF returns `403` with no body. A bad Origin or Host returns
72
- `403` with a short plaintext reason.
73
-
74
- ## Transaction log + rollback
75
-
76
- Every `POST /api/apply` writes append-only JSONL entries to
77
- `<projectRoot>/agents/runtime/gui/install-<ts>.log`. Shapes are
78
- declared in
79
- [`types.ts § TransactionLogEntry`](../../packages/core/installer/src/gui/types.ts):
80
-
81
- - `start` workspaces + packs selected
82
- - `plan` — one entry per planned write (`path`, `pack`)
83
- - `commit` `filesWritten`, `lockfileSha256`
84
- - `cancel` explicit `POST /api/cancel`
85
- - `error` terminating failure with `message`
86
-
87
- The next `--gui` boot inspects the most recent log and offers to roll
88
- back if it ended on `start`/`plan`/`error` without a matching
89
- `commit`/`cancel`. The CLI path consumes the same log, so a mid-install
90
- crash can be undone from either entry point.
77
+ Versioned under `/api/v1/`. Selected routes:
78
+
79
+ | Method | Path | Purpose |
80
+ |--------|-------------------------------|-------------------------------------------------------------------------|
81
+ | GET | `/` | SPA shell (token passed via the `?token=` query) |
82
+ | GET | `/api/v1/wizard/state` | Resumable partial wizard state |
83
+ | POST | `/api/v1/wizard/state` | Persist state between steps |
84
+ | GET | `/api/v1/wizard/manifest` | Locked discovery-manifest (extended mode) |
85
+ | GET | `/api/v1/wizard/auto-detect` | Project-signal evidence for the `ai-tools` step (extended mode) |
86
+ | POST | `/api/v1/wizard/finish` | 2PC commit of settings + user-identity |
87
+ | POST | `/api/v1/wizard/apply` | **Single real-apply route.** `dry_run:true` → buffered plan preview; otherwise SSE-streams `scripts/install.py --apply-payload` |
88
+ | GET | `/api/v1/install/detect` | Scope + project shape + tool presence |
89
+ | POST | `/api/v1/install/plan` | Plan preview (per-tool file counts + conflicts) for the Review step |
90
+ | GET | `/api/v1/install/recovery` | Interrupted-run recovery state |
91
+ | GET | `/api/v1/install/legacy-v3` | v3-install detection (backup screen) |
92
+
93
+ The TypeScript apply engine and its `POST /api/v1/install/apply` SSE route
94
+ were removed (road-to-single-install-source-of-truth § Phase 3). All real
95
+ writes now flow through `POST /api/v1/wizard/apply` `scripts/install.py`.
96
+
97
+ Every request passes three `onRequest` hooks in
98
+ [`src/server/app.ts`](../../src/server/app.ts): a `Host`-header allow-list,
99
+ an `Origin` allow-list (browser-issued requests), and a per-server bearer
100
+ token (`Authorization: Bearer <token>`, minted at boot, surfaced in the
101
+ `?token=` URL). A bad token / Host / Origin returns `403`.
102
+
103
+ ## Real apply — single source of truth
104
+
105
+ `POST /api/v1/wizard/apply` is the only write path:
106
+
107
+ - `dry_run: true` spawns `install.py --apply-payload <tmp> --dry-run` and
108
+ returns the buffered plan-summary text (used by the Review preview).
109
+ - otherwise → spawns `install.py --apply-payload <tmp>` (real apply) and
110
+ **streams** the installer's NDJSON stdout
111
+ (`{type:"file",…}` / `{type:"done"|"error"}`) mapped to the SSE frames the
112
+ SPA consumes. The child is killed if the client disconnects
113
+ (abort-on-disconnect, Finding #24). The installer owns its own
114
+ transactional state (the user-scope lockfile + project manifest), so the
115
+ GUI does not maintain a parallel transaction log.
91
116
 
92
117
  ## SSE event framing
93
118
 
94
- Every `POST /api/apply` event is `data: <json>\n\n`. The terminal event
95
- is one of:
119
+ Each real-apply event is `data: <json>\n\n`. Frames:
96
120
 
97
121
  ```jsonc
98
- { "type": "done", "filesWritten": 12, "lockfileSha256": "<64-hex>" }
99
- { "type": "error", "message": "<reason>" }
122
+ { "type": "progress", "file": "<tool>", "status": "deployed", "written": 1, "total": 3 }
123
+ { "type": "done", "summary": { "written": 3, "total": 3 } }
124
+ { "type": "error", "code": "<code>", "message": "<reason>", "recoverable": false }
100
125
  ```
101
126
 
102
- The browser closes the EventSource on either; the server flushes the
103
- transaction log and unblocks the idle timer.
104
-
105
- ## Tarball budget
106
-
107
- GUI assets under `packages/core/installer/src/gui/` (inlined HTML +
108
- CSS + JS in `static-assets.ts`) must stay **≤ 200 KB compiled**. The
109
- constraint is enforced by reviewer judgment for now; a CI check is
110
- tracked under the Phase 6 follow-ups.
127
+ The browser stops reading on `done` / `error`; the server ends the stream.
111
128
 
112
129
  ## Security failure modes covered
113
130
 
114
- - **Remote exploitation** — loopback bind, Host allowlist, Origin
115
- allowlist, CSRF token, CSP `default-src 'self'`.
116
- - **DNS rebinding** — Host header check covers POSTs that omit
117
- `Origin` (form posts).
118
- - **Zombie servers** — ephemeral port + PID file + last-request idle
119
- timer. Stale PIDs (process gone) are silently overwritten on next
120
- boot; live PIDs block boot with a helpful message.
121
- - **Mid-install crash** — transaction log + boot-time rollback prompt.
122
- - **Hidden state** — closing the tab triggers idle timeout; no
123
- cross-tab session.
131
+ - **Remote exploitation** — loopback bind, Host allow-list, Origin
132
+ allow-list, per-server bearer token.
133
+ - **DNS rebinding** — Host header check covers POSTs that omit `Origin`.
134
+ - **Mid-install crash** — `scripts/install.py` owns the user-scope
135
+ lockfile + project manifest; the recovery routes
136
+ (`/api/v1/install/recovery`) surface an interrupted run on next boot.
124
137
 
125
138
  ## Non-goals (documented contract)
126
139
 
127
- - Not a hosted SaaS — no auth, no account model, no telemetry.
128
- - Not a settings editorread-only on the lockfile; writes go
129
- through the same install plan as the CLI.
130
- - Not a CI surface — every operation is reachable via `--gui-port=0
131
- --no-open` is supported for headless smoke tests, but the canonical
132
- CI path is the flag-driven non-interactive CLI.
140
+ - Not a hosted SaaS — no auth account model, no telemetry.
141
+ - Not a parallel installerthe GUI is a selection front-end; every
142
+ real write goes through `scripts/install.py --apply-payload`.
143
+ - Not a CI surface — `--no-open` headless boots are supported for smoke
144
+ tests, but the canonical CI path is the flag-driven non-interactive CLI.
133
145
 
134
146
  ## Apply payload — versioning handshake (road-to-global-only-install Phase 0.4 · D12)
135
147
 
136
- `/api/apply` accepts a discriminated-union body keyed on
148
+ `POST /api/v1/wizard/apply` accepts a discriminated-union body keyed on
137
149
  `schema_version`. The full JSON Schema lives at
138
150
  [`internal/schemas/wizard-apply-payload.schema.json`](../../internal/schemas/wizard-apply-payload.schema.json).
139
151
 
@@ -142,18 +154,19 @@ tracked under the Phase 6 follow-ups.
142
154
  | `"installer-v1"` | `InstallerPayloadV1` | `{ ai_tools[], configs{}, dry_run? }` — legacy Installer-GUI, AI tools only. |
143
155
  | `"wizard-v2"` | `WizardPayloadV2` | `{ tools[], packs[], settings{}, scope_to_project_only?, dry_run? }` — unified 9-step wizard. |
144
156
 
145
- **D12 (locked).** Single `/api/apply` endpoint with a `schema_version`
157
+ **D12 (locked).** Single apply endpoint with a `schema_version`
146
158
  discriminator — **not** two endpoints with a shared Python backend.
147
- Reasoning: one bind, one CSRF token, one transaction log; the
159
+ Reasoning: one bind, one token, one installer; the
148
160
  Python `scripts/install.py` payload-router branches on
149
161
  `schema_version` before any disk write. The dual-endpoint variant was
150
- considered and rejected for doubling the CSRF + idle-timer surface
151
- with no observability gain.
162
+ considered and rejected for doubling the surface with no gain.
152
163
 
153
164
  `schema_version` is **required**. Servers MUST reject any body that
154
- lacks it (HTTP 400, single-line error pointing at the schema). This
155
- locks the contract before Phase 1 implementation so no implicit fork
156
- can sneak in at Phase 1.5.
165
+ lacks it (HTTP 4xx, single-line error pointing at the schema). The
166
+ real-apply path is now wired end-to-end
167
+ (road-to-single-install-source-of-truth § Phases 1–2): `install.py`
168
+ translates the payload into the canonical install and streams NDJSON
169
+ progress back to the GUI.
157
170
 
158
171
  ## Unified 9-step flow (road-to-global-only-install § Phase 1.6)
159
172
 
@@ -25,7 +25,7 @@ Companion artefacts:
25
25
  - Roadmap: [`agents/roadmaps/road-to-internal-ai-os-deployment.md`](../../agents/roadmaps/road-to-internal-ai-os-deployment.md)
26
26
  - Artefacts: [`packages/core/deploy/`](../../packages/core/deploy/)
27
27
  - Env contract: [`docs/deploy/env-vars.md`](../deploy/env-vars.md)
28
- - Council question (drafted, not invoked — no keys): [`agents/tmp/council-question-deployment-shape.md`](../../agents/tmp/council-question-deployment-shape.md)
28
+ - Council question (drafted, not invoked — no keys): [`agents/tmp/council-question-deployment-shape.md`](../../agents/tmp/old/council-question-deployment-shape.md)
29
29
  - Predecessor ADR: [`ADR-016`](ADR-016-installer-architecture.md) — installer architecture (agent-mode protocol the GUI server wraps).
30
30
 
31
31
  ## Context
@@ -141,7 +141,7 @@ orchestrator-agnostic.
141
141
  ## Open questions (council-deferred)
142
142
 
143
143
  The accompanying council question file
144
- [`agents/tmp/council-question-deployment-shape.md`](../../agents/tmp/council-question-deployment-shape.md)
144
+ [`agents/tmp/council-question-deployment-shape.md`](../../agents/tmp/old/council-question-deployment-shape.md)
145
145
  has not yet been run (no provider keys configured). A maintainer with
146
146
  keys should run it and either ratify or supersede this ADR.
147
147
 
@@ -6,7 +6,7 @@
6
6
  > and Phase 3 (central policy) shipping first.
7
7
  >
8
8
  > Open design questions live in
9
- > [`agents/tmp/council-question-connector-scope.md`](../../agents/tmp/council-question-connector-scope.md).
9
+ > [`agents/tmp/council-question-connector-scope.md`](../../agents/tmp/old/council-question-connector-scope.md).
10
10
 
11
11
  ## Audience
12
12
 
@@ -124,6 +124,6 @@ All of the above land in Phase 5, contingent on Phases 2 + 3.
124
124
  ## Cross-references
125
125
 
126
126
  - 🚧 Reserved ADR slot: `docs/decisions/ADR-025-connector-scope.md`.
127
- - Council question: [`agents/tmp/council-question-connector-scope.md`](../../agents/tmp/council-question-connector-scope.md).
127
+ - Council question: [`agents/tmp/council-question-connector-scope.md`](../../agents/tmp/old/council-question-connector-scope.md).
128
128
  - Quickstart: [`quickstart.md`](quickstart.md).
129
129
  - Policy cookbook: [`policy-cookbook.md`](policy-cookbook.md).
@@ -7,7 +7,7 @@
7
7
  > before code lands. Every section below is normative-once-shipped.
8
8
  >
9
9
  > Open design questions live in
10
- > [`agents/tmp/council-question-central-policy.md`](../../agents/tmp/council-question-central-policy.md).
10
+ > [`agents/tmp/council-question-central-policy.md`](../../agents/tmp/old/council-question-central-policy.md).
11
11
 
12
12
  ## Audience
13
13
 
@@ -125,6 +125,6 @@ All of the above land in Phase 3. Until then, per-user
125
125
  ## Cross-references
126
126
 
127
127
  - 🚧 Reserved ADR slot: `docs/decisions/ADR-023-central-policy.md`.
128
- - Council question: [`agents/tmp/council-question-central-policy.md`](../../agents/tmp/council-question-central-policy.md).
128
+ - Council question: [`agents/tmp/council-question-central-policy.md`](../../agents/tmp/old/council-question-central-policy.md).
129
129
  - Env contract: [`env-vars.md`](env-vars.md) (`POLICY_PATH`).
130
130
  - Quickstart: [`quickstart.md`](quickstart.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Universal AI Agent OS \u2014 audited skills, governance rules, commands, and templates for AI coding tools (Claude Code, Cursor, Windsurf, Copilot).",
5
5
  "license": "MIT",
6
6
  "private": false,