From 68ade69de3f7a8451565c8e6b72d0651644cd1ca Mon Sep 17 00:00:00 2001 From: Noah Ingwers <98993329+noah-ing@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:40:15 -0500 Subject: [PATCH 1/2] docs: clarify Guard boundary and add CI --- .github/ISSUE_TEMPLATE/guard-pilot.yml | 63 ---------- .github/workflows/ci.yml | 46 +++++++ LICENSE-MIT | 21 ++++ README.md | 164 ++++++++++++++++++++----- SECURITY.md | 66 ++++++++++ package.json | 6 +- src/pilot-applications.mjs | 2 +- 7 files changed, 268 insertions(+), 100 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/guard-pilot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 LICENSE-MIT create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/guard-pilot.yml b/.github/ISSUE_TEMPLATE/guard-pilot.yml deleted file mode 100644 index bb9b31a..0000000 --- a/.github/ISSUE_TEMPLATE/guard-pilot.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: GoldKey Guard founding pilot -description: Apply for a scoped, paid enforcement integration pilot. -title: "[Guard pilot] " -body: - - type: markdown - attributes: - value: | - GoldKey Guard founding pilots are **$1,000** for one environment, one connector, one immutable operator policy, and up to two hours of integration support. Successful authorization decisions are billed at **$0.05 for MCP/HTTPS** or **$0.10 for EVM** through x402 on Base. ALLOW, REVIEW, and BLOCK decisions are billable; exact unexpired replays are not. - - This issue is public. Do not include credentials, private keys, wallet seed phrases, confidential payloads, customer data, internal URLs, or proprietary policy contents. - - type: dropdown - id: connector - attributes: - label: Connector type - description: Choose the first execution path you want to enforce. - options: - - MCP tool call - - HTTPS request - - EVM transaction - validations: - required: true - - type: input - id: environment - attributes: - label: Environment - description: A non-secret description such as staging, production canary, or one isolated agent. - placeholder: Production canary for one routing agent - validations: - required: true - - type: textarea - id: problem - attributes: - label: Action that must be enforced - description: Describe the proposed action, the irreversible failure you need to prevent, and how the local enforcer will be the exclusive path. Do not paste real requests or secrets. - placeholder: Prevent unapproved external seller calls before our router forwards credentials or signs a payment. - validations: - required: true - - type: input - id: volume - attributes: - label: Expected monthly authorizations - placeholder: 10,000 - validations: - required: true - - type: dropdown - id: timeline - attributes: - label: Integration timeline - options: - - Within 7 days - - Within 30 days - - More than 30 days - validations: - required: true - - type: checkboxes - id: commercial - attributes: - label: Commercial fit - options: - - label: I understand the $1,000 pilot fee and metered authorization pricing stated above. - required: true - - label: I can run the local enforcer as the exclusive path to the protected credential, connector, or signer. - required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..dbe963f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI + +"on": + pull_request: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + name: Service, enforcer, and contract tests + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Check out repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22.22.0" + package-manager-cache: false + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 + with: + version: v1.5.1 + cache: false + + - name: Install locked dependencies + run: | + npm ci + npm --prefix enforcer ci + + - name: Check Solidity formatting + run: forge fmt --root contracts --check + + - name: Run all test suites + run: npm run check diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..4215f89 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Noah Ingwers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 9cc388b..0f50e04 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,107 @@ -# GoldKey +# GoldKey Guard + +GoldKey Guard is an execution-path authorization layer for AI agents. An +operator-controlled local enforcer holds the protected MCP or HTTPS credential, +transport, or signer for supported Base/EVM actions. It forwards a proposed +call only after verifying a short-lived signed `ALLOW` receipt bound to the +exact call, installation, and active operator policy. + +## Security boundary + +Guard is an enforcement boundary only when the agent cannot bypass the local +enforcer to reach the protected capability directly. The hosted authorizer +receives the canonical proposed call, public installation identity and +signature, and any authorization-payment evidence. It does not receive the +protected upstream credential or execution signer, and it never invokes, +signs, broadcasts, or forwards the protected action. + +The fail-closed sequence is: + +1. The operator defines an immutable policy and fixed connector allowlist + outside the agent's control. +2. The local installation canonicalizes and signs the exact proposed call and + durable idempotency key. +3. The hosted authorizer returns a signed `ALLOW`, `REVIEW`, or `BLOCK` decision + bound to the call, installation, policy, and expiry window. +4. The local enforcer verifies that binding and invokes its operator-bound + connector only for a fresh `ALLOW`. `REVIEW` and `BLOCK` never forward. +5. A timeout or crash after forwarding becomes `outcome_unknown`; the enforcer + does not automatically replay an irreversible action. + +The threat model is a compromised or misdirected agent proposing an +unauthorized, altered, over-budget, or replayed action. Guard cannot enforce a +capability that remains reachable through another credential, signer, network +route, or process. Its receipts attest GoldKey's observations and authorization +decision; they do not prove universal safety or an upstream outcome that +GoldKey did not independently observe. See +[GUARD_PRODUCT.md](GUARD_PRODUCT.md) for supported operations, trust +assumptions, adapter limits, DNS and spend controls, and recovery boundaries. + +## Beta status and evidence + +- Guard is a feature-gated design-partner beta. Registration requires an + exactly allowlisted operator wallet, and the hosted routes are disabled by + default until their payment, signing, and allowlist configuration is valid. +- The local enforcer is available as the integrity-pinned + [v0.2.1 beta prerelease](https://github.com/noah-ing/goldkey/releases/tag/v0.2.1). + Verify the attached manifest before installing the tarball. +- The repository includes service, enforcer, and contract tests for policy and + schema drift, exact-call and receipt binding, replay and idempotency, + concurrent spend reservations, destination controls, lifecycle failures, + and supported EVM constraints. +- This beta is not independently audited or certified. It is not a compliance + certification, blanket penetration test, production guarantee, or claim + that every vulnerability will be found or prevented. + +### Verify locally + +Requires Node.js 22 or newer and Foundry: -GoldKey is a fixed-price, transferable NFT access pass sold directly to autonomous agents. +```sh +npm ci +npm --prefix enforcer ci +npm run check +``` + +The two clean installs use the root lockfile and the enforcer's separately +pinned dependency manifest. `npm run check` runs the service/API, +local-enforcer, and Solidity contract test suites. `npm run demo` separately +exercises deterministic quote logic and the prompt scanner without submitting +a transaction. + +Implementation and operating details: + +- [Local enforcer security boundary and installation](enforcer/README.md) +- [Guard product model and non-negotiable security properties](GUARD_PRODUCT.md) +- [Testnet, mainnet, and acceptance runbook](DEPLOYMENT.md) +- [Guarded staging pilot scope and exclusions](SECURITY_PILOT.md) +- [Private vulnerability reporting and supported versions](SECURITY.md) + +## Guarded integration pilot + +GoldKey offers a fixed-fee **$10,000 guarded integration pilot** for teams +preparing to let one AI-agent workflow call a privileged MCP tool, HTTPS +operation, or supported Base/EVM wallet action. The engagement is delivered in +two independently accepted $5,000 milestones and is limited to a customer-owned +staging environment, one workflow, and one connector path. + +The pilot includes a threat model, immutable operator policy, a +customer-controlled local enforcement path, adversarial +allow/deny/replay/drift tests, an evidence package, and an operational handoff. +A smaller $1,000 control-design sprint is available when the integration +boundary is not yet ready to implement. + +See [SECURITY_PILOT.md](SECURITY_PILOT.md) for scope, acceptance criteria, +exclusions, and commercial terms, then use the +[private pilot application](https://goldkey-edge-storefront.noah-ing.workers.dev/#pilot-application) +to describe one concrete workflow and connector. No work begins without +written authorization and a funded milestone. + +## Commerce and deterministic utilities + +Separate from Guard, GoldKey includes an optional fixed-price, transferable +ERC-721 access pass and x402 paygo layer for deterministic agent utilities. The +pass is an API entitlement, not an investment. - Primary price: **50 USDC** - Hard primary supply cap: **10,000** @@ -10,23 +111,18 @@ GoldKey is a fixed-price, transferable NFT access pass sold directly to autonomo - Public alternative: **0.01 USDC per call** through x402 - Mechanical break-even: **5,000 calls per key**, before gas and switching cost -The NFT is not sold on a speculative story. It is the transferable settlement object for a cost-saving API entitlement. At 10,000 calls, paygo costs 100 USDC and GoldKey costs 50 USDC. High-volume orchestrators can issue revocable child-agent keys so an entire swarm draws from one quota. - -The 500,000-USDC figure is the maximum gross from first mints, not a sales forecast and not a cap on total revenue. Renewal and paygo revenue are separate and are not supply-capped. The commercial bottleneck is distribution to agents that genuinely exceed 5,000 eligible calls per term. - -## Paid security integration +At 10,000 calls, paygo costs 100 USDC and the pass costs 50 USDC before gas, +switching cost, and risk reserve. High-volume orchestrators can issue revocable +child-agent keys so multiple workers draw from one quota. The 500,000-USDC +figure is the maximum gross from first mints, not a sales forecast or a cap on +renewal and paygo revenue. -GoldKey also offers a fixed-fee **$10,000 guarded integration pilot** for teams preparing to let one AI-agent workflow call a privileged MCP tool, HTTPS operation, or supported Base/EVM wallet action. The engagement is delivered in two independently accepted $5,000 milestones and is limited to a customer-owned staging environment, one workflow, and one connector path. +GoldKey's four live x402 resources are independently indexed on +[x402scan](https://www.x402scan.com/server/8447beac-d24b-434a-bd01-5abfdab53f84), +including the Action Gate, Agent Utilities, Network Authorization, and EVM +Authorization endpoints. -The pilot includes a threat model, immutable operator policy, a customer-controlled local enforcement path, adversarial allow/deny/replay/drift tests, an evidence package, and an operational handoff. A smaller $1,000 control-design sprint is available when the integration boundary is not yet ready to implement. - -See [SECURITY_PILOT.md](SECURITY_PILOT.md) for scope, acceptance criteria, exclusions, and commercial terms, then use the [private pilot application](https://goldkey-edge-storefront.noah-ing.workers.dev/#pilot-application) to describe one concrete workflow and connector. No work begins without written authorization and a funded milestone. - -GoldKey's four live x402 resources are independently indexed on [x402scan](https://www.x402scan.com/server/8447beac-d24b-434a-bd01-5abfdab53f84), including the Action Gate, Agent Utilities, Network Authorization, and EVM Authorization endpoints. - -The locally tested Guard enforcer is available as an integrity-pinned [v0.2.1 beta prerelease](https://github.com/noah-ing/goldkey/releases/tag/v0.2.1). Verify the attached manifest before installing the local tarball. This beta is not independently audited or certified. - -## What is included +### Included commerce and access controls - Fixed 50-USDC, 10,000-supply ERC-721 contract - Onchain term number, expiration, renewal, immutable price/cap/terms hash @@ -56,21 +152,11 @@ The locally tested Guard enforcer is available as an integrity-pinned [v0.2.1 be Every successful NFT-gated tool result costs one quota unit. Exact NFT-gated idempotent retries are replayed without a second debit. Each paygo request is a separate 0.01-USDC x402 purchase. The service checks the tool name and request shape before payment verification; after verification it fully validates and executes the tool, buffers the result, settles payment, and releases the result only after successful settlement. A tool error cancels settlement. Paygo does not use the NFT idempotency ledger, so retrying a successfully settled paygo call is another purchase. -## Run it +## Run the local service -Requires Node 22 or newer and Foundry for contract tests. - -```sh -npm install -npm run check -npm run demo -``` - -`pg` was added while this workspace had no registry access. The first connected -`npm install` refreshes `package-lock.json`; commit that refreshed lock, then use -`npm ci` for reproducible builds. - -Copy `.env.example` to `.env`, set the RPC and deployed addresses, then: +After the verified install and test sequence above, `npm run demo` runs the +offline quote-and-utility example. To start the API locally, copy `.env.example` +to `.env` and set the RPC and deployed addresses: ```sh npm start @@ -157,8 +243,8 @@ Each input line is a quote request; each output line is a strict JSON commerce r `distribution/goldkey-agent-utilities/` is a ClawHub-ready OpenClaw skill with a no-dependency Node client for discovery, live quotes, authentication, quota, and pass-gated tool calls. Its client pins the verified Base-mainnet Worker, -contract, canonical USDC, and frozen terms hash. Confirm no release placeholders -remain and run its `self-test` before publishing an update. +contract, canonical USDC, and frozen terms hash. Before publishing an update, +run its `self-test` and compare every pinned value with live discovery. Publish the free integration under the `integrations`, `security`, and `finance` categories. The external service remains paid at the posted prices; ClawHub is @@ -214,3 +300,15 @@ See `TERMS.md` for the exact hashed entitlement, `ZERO_CASH_LAUNCH.md` for the capital-free route, `DEPLOYMENT.md` for the complete testnet/mainnet runbook, `edge/README.md` for the always-on storefront, and `CREATE2_DEPLOYMENT.md` for the offline sponsored-deployment manifest builder. + +## License + +Unless a file states otherwise, this repository is distributed under the +[ISC License](LICENSE). The enforcer carries the same ISC text in +[enforcer/LICENSE](enforcer/LICENSE). + +The Solidity contract and its Solidity test declare +`SPDX-License-Identifier: MIT` and are distributed under the +[MIT License](LICENSE-MIT): `contracts/src/GoldKey.sol` and +`contracts/test/GoldKey.t.sol`. Third-party dependencies and generated +dependency metadata retain their own license terms. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..1193d16 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,66 @@ +# Security Policy + +GoldKey Guard is beta software and has not been independently audited or +certified. Security reports are welcome; this policy does not create a bug +bounty, service-level agreement, or guarantee of payment. + +## Supported versions + +| Component | Status | +|---|---| +| Current main branch and hosted beta | Supported | +| Local enforcer v0.2.1 | Supported | +| Earlier enforcer prereleases | Unsupported; reproduce against v0.2.1 first | + +## Report a vulnerability privately + +Use GitHub's private advisory form: + +https://github.com/noah-ing/goldkey/security/advisories/new + +If that form is unavailable, open a public issue that asks for a private +reporting channel, but include no exploit details, credentials, customer data, +or vulnerable endpoint parameters in the issue. + +Include, when possible: + +- the affected component, version, and commit; +- the security boundary or invariant that can be bypassed; +- minimal reproduction steps using test accounts and testnet assets; +- expected and observed behavior; +- impact, preconditions, and any suggested remediation; and +- whether the issue is already public or under active exploitation. + +Do not test against another person's wallet, installation, data, credentials, +or production workflow. Do not submit irreversible mainnet transactions, +degrade the hosted service, exfiltrate data, or retain data beyond what is +strictly necessary to demonstrate the issue. + +## Priority areas + +High-value reports include: + +- forged, replayed, expired, or incorrectly bound authorization receipts; +- bypasses that let an agent reach a protected connector or signer directly; +- policy, schema, destination, spend, idempotency, or installation-binding + failures; +- extraction of protected upstream credentials or signing material; +- payment or quota accounting errors that create unauthorized execution; and +- transaction-construction flaws that violate documented EVM constraints. + +Reports about expected beta limitations, unsupported deployment topologies, +denial of service without a security boundary bypass, social engineering, or +issues that require prior compromise of the operator-controlled host may be +closed as out of scope. + +## Handling and disclosure + +The maintainer will aim to acknowledge a complete report within three business +days, provide a preliminary assessment within seven business days, and +coordinate remediation and disclosure based on severity and exploitability. +These are targets, not guarantees. + +Please allow a reasonable remediation window before public disclosure. +Good-faith research that follows this policy, minimizes harm, and complies with +applicable law will not be pursued by the maintainer merely for identifying +and privately reporting a vulnerability. diff --git a/package.json b/package.json index ee61f3c..c49781b 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "dev": "NODE_ENV=development node --watch src/server.mjs", "test": "node --test --test-concurrency=1 test/*.test.mjs", "test:enforcer": "npm --prefix enforcer test", - "test:contract": "/Users/noah-ing/.foundry/bin/forge test --root contracts --offline -vv", - "fmt:contract": "/Users/noah-ing/.foundry/bin/forge fmt --root contracts", - "check": "npm test && npm run test:enforcer && npm run test:contract", + "test:contract": "forge test --root contracts -vv", + "fmt:contract": "forge fmt --root contracts", + "check": "npm run test:contract && npm test && npm run test:enforcer", "deployment:create2": "node scripts/build-create2-deployment.mjs", "deployment:create2:dry-run": "node scripts/build-create2-deployment.mjs --sample-sepolia", "demo": "node scripts/demo.mjs", diff --git a/src/pilot-applications.mjs b/src/pilot-applications.mjs index ff94728..1400fb1 100644 --- a/src/pilot-applications.mjs +++ b/src/pilot-applications.mjs @@ -105,7 +105,7 @@ function pageLimit(value) { function normalizePublicBody(body) { exactObject(body, PUBLIC_FIELDS, "invalid_pilot_application", "Pilot application"); if (body.budget_confirmed !== true) { - throw new ServiceError(400, "pilot_budget_not_confirmed", "The $1,000 implementation pilot budget must be confirmed"); + throw new ServiceError(400, "pilot_budget_not_confirmed", "The selected engagement budget must be confirmed"); } return { name: text(body.name, "name", { minimum: 2, maximum: 100 }), From 3d6f58d4861945578b97cd6fd29f684d218c06e2 Mon Sep 17 00:00:00 2001 From: Noah Ingwers <98993329+noah-ing@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:45:42 -0500 Subject: [PATCH 2/2] ci: make generated skill checks portable --- .github/workflows/ci.yml | 5 ++ .../goldkey-agent-utilities.tar.gz | Bin 16273 -> 57364 bytes .../.well-known/agent-skills/index.json | 2 +- scripts/build-domain-skill.mjs | 46 ++++++++++++++++-- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbe963f..fcab197 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,11 @@ jobs: version: v1.5.1 cache: false + - name: Install script runtime + run: | + sudo apt-get update + sudo apt-get install --yes zsh + - name: Install locked dependencies run: | npm ci diff --git a/edge/public/.well-known/agent-skills/goldkey-agent-utilities.tar.gz b/edge/public/.well-known/agent-skills/goldkey-agent-utilities.tar.gz index e11c41e3ed5a794d9559896eb593ac23e45ea697..a268f3f8c31c30e5806e3faf9263cc2830e65103 100644 GIT binary patch literal 57364 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 L_{-n^@|XVupw-2> literal 16273 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 H0N?-s9X_{q diff --git a/edge/public/.well-known/agent-skills/index.json b/edge/public/.well-known/agent-skills/index.json index a55078e..1360808 100644 --- a/edge/public/.well-known/agent-skills/index.json +++ b/edge/public/.well-known/agent-skills/index.json @@ -6,7 +6,7 @@ "type": "archive", "description": "Preflight proposed agent actions with GoldKey Action Gate for a deterministic ALLOW, REVIEW, or BLOCK receipt, or integrate the feature-gated GoldKey Guard beta as an operator-controlled enforcement path for actual MCP, HTTPS, AgentCash, or supported Base/EVM calls. Use for x402-paid action screening, policy enforcement before tool calls or wallet transactions, Guard installation and recovery, component JSON, prompt, URL, spend, and Unicode checks, pass-versus-paygo decisions, or GoldKey pass authentication, quota, and scoped child-key operations.", "url": "./goldkey-agent-utilities.tar.gz", - "digest": "sha256:b477e11175562af5af621b064624636d23de33ae31033201a547cc9066092822" + "digest": "sha256:ed5fdb0614a64e874a23b2ace7436b480d6a511ffb38882a27caaea1c11c6b62" } ] } diff --git a/scripts/build-domain-skill.mjs b/scripts/build-domain-skill.mjs index b70a5df..6dd880b 100644 --- a/scripts/build-domain-skill.mjs +++ b/scripts/build-domain-skill.mjs @@ -3,7 +3,6 @@ import { createHash } from "node:crypto"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { dirname, resolve } from "node:path"; -import { deflateRawSync } from "node:zlib"; import { fileURLToPath } from "node:url"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); @@ -83,9 +82,50 @@ function crc32(bytes) { return (crc ^ 0xffffffff) >>> 0; } +function reverseBits(value, width) { + let reversed = 0; + for (let bit = 0; bit < width; bit += 1) { + reversed = (reversed << 1) | ((value >>> bit) & 1); + } + return reversed; +} + +function fixedLiteralCode(symbol) { + if (symbol <= 143) return [0x30 + symbol, 8]; + if (symbol <= 255) return [0x190 + symbol - 144, 9]; + if (symbol <= 279) return [symbol - 256, 7]; + return [0xc0 + symbol - 280, 8]; +} + +function deterministicDeflate(bytes) { + const output = []; + let pending = 0; + let pendingBits = 0; + + const writeBits = (value, width) => { + pending |= value << pendingBits; + pendingBits += width; + while (pendingBits >= 8) { + output.push(pending & 0xff); + pending >>>= 8; + pendingBits -= 8; + } + }; + + writeBits(0b011, 3); // final block using the fixed Huffman table + for (const byte of bytes) { + const [code, width] = fixedLiteralCode(byte); + writeBits(reverseBits(code, width), width); + } + const [endCode, endWidth] = fixedLiteralCode(256); + writeBits(reverseBits(endCode, endWidth), endWidth); + if (pendingBits > 0) output.push(pending & 0xff); + return Buffer.from(output); +} + function deterministicGzip(bytes) { - const header = Buffer.from([0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff]); - const compressed = deflateRawSync(bytes, { level: 9 }); + const header = Buffer.from([0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]); + const compressed = deterministicDeflate(bytes); const trailer = Buffer.alloc(8); trailer.writeUInt32LE(crc32(bytes), 0); trailer.writeUInt32LE(bytes.length >>> 0, 4);