@nurix/etna 0.19.75 → 0.19.76

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "fingerprint": "a4e2f407bbc6",
2
+ "fingerprint": "ae6ba8fb523a",
3
3
  "harnesses": {
4
4
  "code": {
5
5
  "plugin": "code",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "harness": "code",
3
3
  "name": "code",
4
- "version": "3.9.6",
4
+ "version": "3.10.2",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
@@ -15,5 +15,5 @@
15
15
  "docs/memory/main.md",
16
16
  ".mcp.json"
17
17
  ],
18
- "digest": "f1da48ec8895"
18
+ "digest": "7eff5a4d7de8"
19
19
  }
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
10
10
  | The user asks for a changelog | The entry for the work in hand. No commit required |
11
11
  | A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
12
12
 
13
- An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
14
-
15
13
  Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
16
14
 
17
15
  ## Lifecycle
@@ -6,30 +6,37 @@ Conventions for Cloudflare Workers — `wrangler.jsonc` setup, vars and secrets,
6
6
 
7
7
  ### 1.1 Wrangler version
8
8
 
9
- - Use Wrangler **v4** — v3's bundled config schema is missing newer keys (e.g. `secrets_store_secrets`), so editors flag valid config as invalid.
10
- - **No `package.json`** (dep-free worker): use `npx wrangler@4` in every command and doc — the `@4` is the pin. Don't create a `package.json` just to record it.
9
+ - Use Wrangler **v4**. If an editor flags valid config as invalid, check the wrangler version first.
10
+ - **No `package.json`** (dep-free worker): use `npx wrangler@4` in every command and doc. Never create a `package.json` just to record the version.
11
11
  - **`package.json` exists**: pin wrangler to the exact version tested against (not `^4.0.0`), reinstall, and verify with `wrangler deploy --dry-run` before pushing.
12
12
 
13
13
  ### 1.2 Config format
14
14
 
15
15
  - Use `wrangler.jsonc` (not `wrangler.toml`).
16
- - Include `"$schema": "node_modules/wrangler/config-schema.json"` so the editor validates against the exact installed wrangler version.
16
+ - Include `"$schema": "node_modules/wrangler/config-schema.json"`.
17
17
 
18
18
  ### 1.3 Comments in jsonc
19
19
 
20
20
  None by default. Keep a comment only when it captures a non-obvious **WHY** — a hidden constraint, workaround, or account-specific quirk. Never narrate what a key already says.
21
21
 
22
- ### 1.4 workers.dev URLs
22
+ ### 1.4 Public entry points — workers.dev & preview URLs
23
23
 
24
- - **Don't expose on `workers.dev` by default** — it is a public, guessable, internet-facing domain (`<worker>.<account>.workers.dev`), indexed and reachable by anyone the moment the Worker deploys. Default to `"workers_dev": false`; when a deploy is requested and no custom domain or route exists yet, warn the user that enabling `workers.dev` makes the Worker public, and enable it only if they confirm they want that.
25
- - Set `"workers_dev": false` once a custom domain is wired up, so the custom domain is the only entry point.
26
- - Pair with a `routes` entry using `custom_domain: true` so Cloudflare manages the DNS record and cert.
24
+ - **Don't expose on `workers.dev` by default** — it is public and guessable (`<worker>.<account>.workers.dev`). Default to `"workers_dev": false`; when a deploy is requested and no custom domain or route exists yet, warn the user that enabling it makes the Worker public and enable it only on confirmation.
25
+ - **`preview_urls` is a second public door** (`<version>-<worker>.<account>.workers.dev`) — `workers_dev` alone is not the whole switch. Set `"preview_urls": false` with it.
26
+ - Pair a custom domain with a `routes` entry using `custom_domain: true`. **The zone must be in the same account as the Worker** — a route pointing at a zone the account doesn't hold fails at deploy, so check the zone before writing the route.
27
+ - **Declare both keys explicitly, in the same edit that adds the route** — never leave them to the implicit default, and never delete them as redundant once a route exists.
27
28
 
28
- ### 1.5 Observability
29
+ > **Adding a route cuts over atomically — you cannot stage it.** The moment a `routes` entry lands, an absent `workers_dev` key disables `workers.dev` on that same deploy; "add the route now, turn it off once the custom domain answers" is not a sequence wrangler will execute. Where the certificate is slow to provision, that gap is downtime — confirm the outage window with the user before cutting over.
29
30
 
30
- Default block for every Worker:
31
+ Deleting a route is likewise a cutover: `workers.dev` does not return until `"workers_dev": true` is set explicitly, and a torn-down hostname `404`s rather than redirecting — callers holding the old URL get no forwarding.
32
+
33
+ ### 1.5 Default config
34
+
35
+ Every Worker carries these keys. Deviate only where a rule below says to.
31
36
 
32
37
  ```jsonc
38
+ "workers_dev": false,
39
+ "preview_urls": false,
33
40
  "observability": {
34
41
  "logs": {
35
42
  "enabled": false,
@@ -38,14 +45,15 @@ Default block for every Worker:
38
45
  }
39
46
  ```
40
47
 
41
- `enabled: false` avoids per-log billing; `invocation_logs: true` keeps the cheap per-request audit trail. **Bootstrap override:** a new Worker (especially cron-only) runs with `enabled: true` until a few real runs look clean — with logs off, `console.log` is visible only live via `npx wrangler tail` and nothing persists after a failed run. Flip back once stable.
48
+ - `workers_dev` / `preview_urls` — entry-point policy and cutover mechanics: §1.4.
49
+ - **Bootstrap override:** a new Worker (especially cron-only) runs `logs.enabled: true` until a few real runs look clean, then flips back — with logs off, `console.log` is live-only via `npx wrangler tail` and nothing persists after a failed run.
42
50
 
43
51
  ### 1.6 Project structure & dependencies
44
52
 
45
53
  - Main entry file: `index.ts`. Reusable helpers: `helper.ts`.
46
- - TypeScript under `strict: true` — wrangler bundles it natively, no separate build step; a minimal `tsconfig.json` ships even in dep-free Workers.
54
+ - TypeScript under `strict: true` — no build step, and a minimal `tsconfig.json` ships even in dep-free Workers.
47
55
  - Don't run `npm run build` or `npm run deploy` in examples.
48
- - **`package.json` / `package-lock.json` are opt-in, not default.** Create them only when code under `src/` imports an npm package at runtime — a Worker on built-in Web/Workers APIs alone needs no manifest; run wrangler, linters, and one-offs via `npx <tool>`. Add both files the moment the first real dep lands. `node_modules/` stays in `.gitignore` either way.
56
+ - **`package.json` / `package-lock.json` are opt-in.** Create them only when code under `src/` imports an npm package at runtime; add both the moment the first real dep lands. Run wrangler, linters, and one-offs via `npx <tool>`. `node_modules/` stays in `.gitignore` either way.
49
57
 
50
58
  ### 1.7 Environment & configuration
51
59
 
@@ -68,15 +76,15 @@ Access in code: `await env.CLICKUP_KEY.get()`.
68
76
 
69
77
  - Repo/dir: `cf-<name>` (e.g. `cf-extract-design`).
70
78
  - Worker name: `<name>` — repo name minus the `cf-` prefix.
71
- - R2 bucket, D1 database, and KV namespace names: equal to the worker name. One name, one resource set.
79
+ - R2 bucket, D1 database, and KV namespace names: equal to the worker name.
72
80
 
73
81
  ### 1.10 Vars & secrets
74
82
 
75
- **Non-secret vars live in the `vars` block in `wrangler.jsonc`** — checked in, one source of truth. Vars are configuration, not runtime state; do not move them to the dashboard. A single-tenant application Worker (one deployment — e.g. Apollo) declares them at the top level; a multi-tenant Worker declares per-tenant vars under each `env.<tenant>` block (§11).
83
+ **Non-secret vars live in the `vars` block in `wrangler.jsonc`**, checked in. Never move them to the dashboard. A single-tenant application Worker declares them at the top level; a multi-tenant Worker declares per-tenant vars under each `env.<tenant>` block (§11).
76
84
 
77
85
  **Secrets never touch git.** Local dev: a gitignored `.dev.vars` (`KEY=VALUE` dotenv, auto-loaded by `wrangler dev`) with a committed `.dev.vars.example` listing the keys and placeholder values. Production: `wrangler secret put <NAME>`, a gitignored `.secrets` file pushed with `wrangler secret bulk .secrets` (or shipped with a deploy via `wrangler deploy --secrets-file .secrets`), or the Secrets Store (§1.8). Never log or echo a secret value.
78
86
 
79
- **No `keep_vars`.** Leave it unset (default `false`) — each deploy reconciles vars to exactly what the config declares. `keep_vars` only guards plaintext vars set out-of-band in the dashboard; it never touches secrets — `wrangler secret put` secrets survive every deploy regardless. Only the multi-tenant pattern sets `keep_vars: true` (§11).
87
+ **No `keep_vars`** — leave it unset. It guards only plaintext vars set out-of-band in the dashboard and never touches secrets; `wrangler secret put` secrets survive every deploy regardless, so never add it to protect them. Only the multi-tenant pattern sets `keep_vars: true` (§11).
80
88
 
81
89
  **Never name a deployed-value file `.env` or `.env.<anything>`** — `wrangler dev` auto-loads a root `.env` as local dev vars, so a prod-valued `.env` silently becomes the local environment on a fresh clone or in CI. Committed `*.example` files carry keys with placeholder values only.
82
90
 
@@ -84,11 +92,11 @@ Access in code: `await env.CLICKUP_KEY.get()`.
84
92
 
85
93
  ### 1.11 Deploys
86
94
 
87
- **Never auto-deploy.** `wrangler deploy` (any variant — `--env`, `versions upload`, etc.) runs only when the user explicitly asks for a deploy. Building, dry-running (`wrangler deploy --dry-run`), and local dev (`wrangler dev`) are fine unprompted; pushing to Cloudflare is not — finish the change, then tell the user it's ready to deploy.
95
+ **Never auto-deploy.** `wrangler deploy` (any variant — `--env`, `versions upload`) runs only when the user explicitly asks. Building, dry-running (`wrangler deploy --dry-run`), and `wrangler dev` are fine unprompted. Finish the change, then tell the user it's ready to deploy.
88
96
 
89
97
  ## 2. Code & Helpers
90
98
 
91
- - Use `generateUuidV7()` in `helper.ts` for IDs (time-sortable UUIDv7).
99
+ - Use `generateUuidV7()` in `helper.ts` for IDs.
92
100
  - Only `await` what's needed (e.g. `request.json()`, `do.fetch(...)`).
93
101
 
94
102
  ## 3. fetch() Structure
@@ -160,13 +168,13 @@ Follows the shared database naming and column-type vocabulary; what earns a tabl
160
168
 
161
169
  ## 11. Multi-tenant Workers (native environments)
162
170
 
163
- Rare — only when **one Worker codebase ships as several independent tenants** (separate Workers, domains, and data stores from a single `src/`, e.g. `~/dev/auth` → `auth-nuplay`, `auth-nustack`). Use **native wrangler environments**, never one Worker that switches tenant at runtime. For a single-tenant application Worker, §1.10 applies and this section does not.
171
+ Rare — only when **one Worker codebase ships as several independent tenants**: separate Workers, domains, and data stores from a single `src/`. Use **native wrangler environments**, never one Worker that switches tenant at runtime. For a single-tenant application Worker, §1.10 applies and this section does not.
164
172
 
165
173
  - **One config, `env.<tenant>` blocks.** The top-level block is **local dev** (`wrangler dev`): a `*-dev` name and placeholder D1/KV ids, simulated locally. Each `env.<tenant>` block is **one production tenant**; deploy it with `wrangler deploy --env <tenant>`.
166
174
  - **Named environments never inherit** `vars` / `d1_databases` / `kv_namespaces` / `routes` / `secrets_store_secrets` / `assets` from the top level — **each `env.<tenant>` declares them in full**. Dropping a binding from an env block disables that capability for that one tenant.
167
- - **Per-tenant non-secret vars live in `env.<tenant>.vars`** — still checked in; one file holds every tenant's config side by side.
175
+ - **Per-tenant non-secret vars live in `env.<tenant>.vars`**, checked in.
168
176
  - **Local-dev vars** come from a gitignored `.vars.local`, injected as `--var` by the dev script (the top-level block carries no in-config `vars`).
169
177
  - **Per-tenant secrets, never in git** — `wrangler secret put <NAME> --env <tenant>`, or a gitignored per-tenant `.secrets` (e.g. `worker/tenants/<tenant>/.secrets`) pushed with `wrangler secret bulk --env <tenant>`, plus a committed `.secrets.example`. Secrets Store bindings are declared inside each env block.
170
178
  - **`keep_vars: true`** (top level) keeps a per-tenant deploy **additive**: tenants inject their non-secret vars via `--var` (or the dashboard), and without it a deploy would wipe them. On secrets it changes nothing (§1.10).
171
179
 
172
- `.gitignore`: `.vars.local`, `.secrets`, `.secrets.*`, `.env`, `.env.*`
180
+ `.gitignore`: §1.10's list, with `.vars.local` in place of `.dev.vars`.
@@ -25,6 +25,6 @@ Every package compiles under `strict: true` and `noUncheckedIndexedAccess: true`
25
25
 
26
26
  Shared libraries (`@nurix/components`, etc.) are generic on purpose — that's what types `cell(row)`, checks `slug` against `keyof TData`, and ties `data`/`columns` together; **never** widen to `any` to dodge it. State the row type **once per file** and let inference carry it — repeating `fn<Type>(…)` / `<Comp<Type>>` per call site is cosmetic (same safety, same emitted JS):
27
27
 
28
- - **Bind a repeated factory once** (preferred): `const col = defineColumn<BriefRow>;` → `col({...})`. Canonical: `modules/briefs/BriefsListPage.tsx`.
29
- - **Infer JSX type args from props:** `<Table data={rows} columns={columns} />`, not `<Table<BriefRow> …>`.
30
- - **Anchor with a collection annotation** when nothing else can: `const columns: ColumnDefinition<BriefRow>[] = [...]`.
28
+ - **Bind a repeated factory once** (preferred): `const col = defineColumn<Row>;` → `col({...})`.
29
+ - **Infer JSX type args from props:** `<Table data={rows} columns={columns} />`, not `<Table<Row> …>`.
30
+ - **Anchor with a collection annotation** when nothing else can: `const columns: ColumnDefinition<Row>[] = [...]`.
@@ -4,13 +4,13 @@ Runtime versions, package policy, the API response envelope, and GitHub Actions
4
4
 
5
5
  ## Runtime Versions
6
6
 
7
- - **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — **never** a hardcoded number, **never** the runner's default. Workflows use `node-version-file: .nvmrc`.
7
+ - **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — never a hardcoded number anywhere.
8
8
  - **Package manager:** detect from the lockfile — **never** hardcode one.
9
9
  - **PostgreSQL:** 17 · **Redis:** 7.x (latest)
10
10
 
11
11
  ## Packages
12
12
 
13
- **Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision. Test packages install at `latest`; fake data comes from `@ngneat/falso` — **never** `@faker-js/faker` / `chance`.
13
+ **Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
14
14
 
15
15
  ## API Response Envelope
16
16
 
@@ -37,4 +37,4 @@ Pin the major, and check it against the action's releases — a major behind sti
37
37
  | `actions/checkout` | v7 | Repo checkout |
38
38
  | `actions/setup-node` | v7 | Node toolchain + npm cache |
39
39
 
40
- Set `node-version` via `node-version-file: .nvmrc`, **never** a hardcoded number and **never** the runner's default.
40
+ Set `node-version` via `node-version-file: .nvmrc`, **never** the runner's default.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "harness": "delivery",
3
3
  "name": "delivery",
4
- "version": "0.2.12",
4
+ "version": "0.2.14",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [],
11
- "digest": "599762913a4e"
11
+ "digest": "3ef9954da94f"
12
12
  }
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
10
10
  | The user asks for a changelog | The entry for the work in hand. No commit required |
11
11
  | A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
12
12
 
13
- An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
14
-
15
13
  Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
16
14
 
17
15
  ## Lifecycle
@@ -178,9 +178,17 @@ The single policy for sub-agent dispatch — when to fan out, at what tier, and
178
178
 
179
179
  ## Authoring Conventions
180
180
 
181
- Most artifacts are markdown — skills, agents, rules, docs. Follow the conventions in `docs/architecture/skills/` and the `kb` / `nomenclature` rules; markdown has no file-path-comment rule. Keep the `.claude/rules/*` reference docs frontmatter-free.
181
+ Most artifacts are markdown — skills, agents, rules, docs. Follow the `kb` / `nomenclature` rules; markdown has no file-path-comment rule. Keep the `.claude/rules/*` reference docs frontmatter-free.
182
182
 
183
- Authoring or updating an **agent** keeps both runtimes in sync: the `.md` is the single source, and its Codex `.codex.toml` twin is derived from it by following [`docs/architecture/harness/authoring-agents.md`](docs/architecture/harness/authoring-agents.md), then checked with `node packages/cli/lib/codex/validate-codex-agents.mjs`.
183
+ **Each artifact class has an authoring guide — read the one you are editing, before you edit it.** The forge is the only repo that authors these, so the guides live here and ship nowhere:
184
+
185
+ | Editing | Guide |
186
+ | --- | --- |
187
+ | A **rule** (`rules/*.md`) | [`docs/architecture/rules.md`](docs/architecture/rules.md) — the catalog, the conventions, and the whole-file audit |
188
+ | A **skill** (`skills/*/`) | [`docs/architecture/skills/playbook/`](docs/architecture/skills/playbook/Readme.md) — fit and scope through shipping and maintenance |
189
+ | An **agent** (`agents/*.md`) | [`docs/architecture/harness/authoring-agents.md`](docs/architecture/harness/authoring-agents.md) |
190
+
191
+ Authoring or updating an **agent** keeps both runtimes in sync: the `.md` is the single source, and its Codex `.codex.toml` twin is derived from it by the guide above, then checked with `node packages/cli/lib/codex/validate-codex-agents.mjs`.
184
192
 
185
193
  For real code (the CLI under `packages/`, hook scripts):
186
194
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "harness": "etna",
3
3
  "name": "etna",
4
- "version": "1.4.11",
4
+ "version": "1.5.1",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [],
11
- "digest": "84ce5acb1a74"
11
+ "digest": "7fbf00581722"
12
12
  }
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
10
10
  | The user asks for a changelog | The entry for the work in hand. No commit required |
11
11
  | A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
12
12
 
13
- An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
14
-
15
13
  Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
16
14
 
17
15
  ## Lifecycle
@@ -4,13 +4,13 @@ Runtime versions, package policy, the API response envelope, and GitHub Actions
4
4
 
5
5
  ## Runtime Versions
6
6
 
7
- - **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — **never** a hardcoded number, **never** the runner's default. Workflows use `node-version-file: .nvmrc`.
7
+ - **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — never a hardcoded number anywhere.
8
8
  - **Package manager:** detect from the lockfile — **never** hardcode one.
9
9
  - **PostgreSQL:** 17 · **Redis:** 7.x (latest)
10
10
 
11
11
  ## Packages
12
12
 
13
- **Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision. Test packages install at `latest`; fake data comes from `@ngneat/falso` — **never** `@faker-js/faker` / `chance`.
13
+ **Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
14
14
 
15
15
  ## API Response Envelope
16
16
 
@@ -37,4 +37,4 @@ Pin the major, and check it against the action's releases — a major behind sti
37
37
  | `actions/checkout` | v7 | Repo checkout |
38
38
  | `actions/setup-node` | v7 | Node toolchain + npm cache |
39
39
 
40
- Set `node-version` via `node-version-file: .nvmrc`, **never** a hardcoded number and **never** the runner's default.
40
+ Set `node-version` via `node-version-file: .nvmrc`, **never** the runner's default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nurix/etna",
3
- "version": "0.19.75",
3
+ "version": "0.19.76",
4
4
  "description": "Bootstrap a project with a Nurix harness — copies the harness's CLAUDE.md, skills, agents, rules, and hooks directly into the project from a bundled payload (no marketplace fetch, no network).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,5 +42,5 @@
42
42
  "agent",
43
43
  "plugin"
44
44
  ],
45
- "etnaFingerprint": "a4e2f407bbc6"
45
+ "etnaFingerprint": "ae6ba8fb523a"
46
46
  }