{"_id":"@hubble-ventures/infisicml","_rev":"4-8bd05eaa70bd62434eb98042760f0a0c","name":"@hubble-ventures/infisicml","dist-tags":{"latest":"3.0.0"},"versions":{"1.2.1":{"name":"@hubble-ventures/infisicml","version":"1.2.1","keywords":["infisical","secrets","monorepo","dotenv","github-actions","ci","env"],"author":{"name":"Hubble Ventures"},"license":"MIT","_id":"@hubble-ventures/infisicml@1.2.1","maintainers":[{"name":"anxious-engineer","email":"david@hubble.ventures"}],"homepage":"https://github.com/hubble-ventures/infisicml#readme","bugs":{"url":"https://github.com/hubble-ventures/infisicml/issues"},"bin":{"infisicml":"dist/cli.js"},"dist":{"shasum":"8829ccd199937d17c1a791776ebe0380b78b6eca","tarball":"https://registry.npmjs.org/@hubble-ventures/infisicml/-/infisicml-1.2.1.tgz","fileCount":97,"integrity":"sha512-Segbva+bBaBQYV74udYvn9Bf2NYYmlfLk9SH9e+yvx6QnCuevfqAVrRzuVjPdVeHHcjxgpZhrWhyc4kzPukOmw==","signatures":[{"sig":"MEQCIED/nvfuSDqY6JvMe4zOi8wR471LcdlpAIBFOJgVdcE+AiB00bZ30yQfDcNT7Ff5rpTB5C7XTSQvGdJfAzdScW919w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":167223},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema":"./schema/secrets.schema.json"},"gitHead":"5f8ac19388b675162849c54ea63b728863132483","scripts":{"test":"vitest run","build":"tsc","clean":"rm -rf dist","smoke":"npm run build && bash scripts/smoke.sh","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"anxious-engineer","email":"david@hubble.ventures"},"repository":{"url":"git+https://github.com/hubble-ventures/infisicml.git","type":"git"},"_npmVersion":"11.16.0","description":"Infisical Secret Orchestration — federated per-package secret manifests for monorepos, unified across local dev and CI.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^3.23.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/infisicml_1.2.1_1784318637108_0.9399794907971606","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@hubble-ventures/infisicml","version":"2.0.0","keywords":["infisical","secrets","monorepo","dotenv","github-actions","ci","env"],"author":{"name":"Hubble Ventures"},"license":"MIT","_id":"@hubble-ventures/infisicml@2.0.0","maintainers":[{"name":"anxious-engineer","email":"david@hubble.ventures"}],"homepage":"https://github.com/hubble-ventures/infisicml#readme","bugs":{"url":"https://github.com/hubble-ventures/infisicml/issues"},"bin":{"infisicml":"dist/cli.js"},"dist":{"shasum":"cb015b5956d95b710ab20db5331377bf00d0d38a","tarball":"https://registry.npmjs.org/@hubble-ventures/infisicml/-/infisicml-2.0.0.tgz","fileCount":101,"integrity":"sha512-m17Rm3dfZTQhbm+PZkupEImd0zUkMcWpdM7fxuxR0tWDIb6vY4eD7j9yfFpCeC7XOciChpRjCfrphpVNbVn7TA==","signatures":[{"sig":"MEYCIQCpCeYt5AuGRBLlcPu57oGMFwBihn4Xsf6v/VVrB3egIgIhAJzBFgdmHkDjPWOkISoW8J6Z4EsD5vxhJCEknmky0GN4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hubble-ventures%2finfisicml@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":176193},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema":"./schema/secrets.schema.json"},"gitHead":"263d3633078f45f17da20bdbd674d53473463307","scripts":{"test":"vitest run","build":"tsc","clean":"rm -rf dist","smoke":"npm run build && bash scripts/smoke.sh","release":"npm version --no-git-tag-version","version":"npm run build","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:db1021a3-c6be-42bd-93f8-8e116a4f44bf"}},"repository":{"url":"git+https://github.com/hubble-ventures/infisicml.git","type":"git"},"_npmVersion":"11.18.0","description":"Infisical Secret Orchestration — federated per-package secret manifests for monorepos, unified across local dev and CI.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/infisicml_2.0.0_1784326194240_0.3283257122673291","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@hubble-ventures/infisicml","version":"2.1.0","keywords":["infisical","secrets","monorepo","dotenv","github-actions","ci","env"],"author":{"name":"Hubble Ventures"},"license":"MIT","_id":"@hubble-ventures/infisicml@2.1.0","maintainers":[{"name":"anxious-engineer","email":"david@hubble.ventures"}],"homepage":"https://github.com/hubble-ventures/infisicml#readme","bugs":{"url":"https://github.com/hubble-ventures/infisicml/issues"},"bin":{"infisicml":"dist/cli.js"},"dist":{"shasum":"5ad51198f91105ed72e6dd46f263aa7dc92ebda4","tarball":"https://registry.npmjs.org/@hubble-ventures/infisicml/-/infisicml-2.1.0.tgz","fileCount":101,"integrity":"sha512-4NtEW2QoQiBWC3YG2pkKoVRAJxzQSL768ElLQbgJdnQ7bzbva3y9l753q/Lh8MfS6f9spdeQ6S3fc3Tf2ojhnQ==","signatures":[{"sig":"MEQCIAYnCO3m9snQHaJB+Qk+6ZPkS4eXHY1QX/wIJGEV6ug6AiAereTM7qePge3Fek/MKIwSwI4jBzQDYcdPQ3N+HePN6w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hubble-ventures%2finfisicml@2.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":189797},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema":"./schema/secrets.schema.json"},"gitHead":"2e8399b7a7c6a2160b0a1a6fb826ff8683cc83f7","scripts":{"test":"vitest run","build":"tsc","clean":"rm -rf dist","smoke":"npm run build && bash scripts/smoke.sh","release":"npm version --no-git-tag-version","version":"npm run build","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:db1021a3-c6be-42bd-93f8-8e116a4f44bf"}},"repository":{"url":"git+https://github.com/hubble-ventures/infisicml.git","type":"git"},"_npmVersion":"11.18.0","description":"Infisical Secret Orchestration — federated per-package secret manifests for monorepos, unified across local dev and CI.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8","yaml":"^2.9.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/infisicml_2.1.0_1784415964924_0.3005095277764436","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@hubble-ventures/infisicml","version":"3.0.0","description":"Declarative Infisical secret manifests for monorepos — pull, validate, and diff per-package secrets, with native GitHub Actions support.","keywords":["infisical","secrets","monorepo","dotenv","github-actions","ci","manifest","env"],"license":"MIT","author":{"name":"Hubble Ventures"},"homepage":"https://github.com/hubble-ventures/infisicml#readme","repository":{"type":"git","url":"git+https://github.com/hubble-ventures/infisicml.git"},"bugs":{"url":"https://github.com/hubble-ventures/infisicml/issues"},"type":"module","publishConfig":{"access":"public"},"bin":{"infisicml":"dist/cli.js"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema":"./schema/secrets.schema.json"},"engines":{"node":">=22"},"packageManager":"pnpm@10.17.1","pnpm":{"onlyBuiltDependencies":["esbuild"]},"scripts":{"gen:schema":"tsx scripts/gen-schema.ts","prebuild":"pnpm gen:schema","build":"tsup && tsc -p tsconfig.build.json","clean":"rm -rf dist action/index.cjs","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","smoke":"pnpm build && node scripts/smoke.mjs","check":"pnpm gen:schema && pnpm typecheck && pnpm test && pnpm build"},"dependencies":{"yaml":"^2.9.0","zod":"^4.4.3"},"devDependencies":{"@types/node":"^22.10.0","tsup":"^8.5.1","tsx":"^4.20.0","typescript":"^7.0.2","vitest":"^4.1.10"},"gitHead":"a36338ed93c53f568c963137f1bfc5cf8188d8e1","_id":"@hubble-ventures/infisicml@3.0.0","_nodeVersion":"24.18.0","_npmVersion":"11.18.0","dist":{"integrity":"sha512-bBOgg5a/kbebjuIKG4ZdpamQdl1uK19oDJn2PKzhiH8/GICVMr34gSil0bJOUHHk0ZdteHPuwpLWGIZHxWcNpQ==","shasum":"5ffe400c1e1fb36e87e2ebc15468f6bf27a7d9be","tarball":"https://registry.npmjs.org/@hubble-ventures/infisicml/-/infisicml-3.0.0.tgz","fileCount":59,"unpackedSize":1096313,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hubble-ventures%2finfisicml@3.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICKnWLNxmY8w4a1cR53/eyQqCiTKoeGlTd6hGKMapi2lAiBHj2Lv4NT03oX0dsRR0hNVfde7f2EZa20AJuvjM7LdOA=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:db1021a3-c6be-42bd-93f8-8e116a4f44bf"}},"directories":{},"maintainers":[{"name":"anxious-engineer","email":"david@hubble.ventures"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/infisicml_3.0.0_1785094377746_0.20307899194489876"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-17T20:03:56.941Z","modified":"2026-07-26T19:32:58.202Z","1.2.1":"2026-07-17T20:03:57.291Z","2.0.0":"2026-07-17T22:09:54.402Z","2.1.0":"2026-07-18T23:06:05.052Z","3.0.0":"2026-07-26T19:32:57.905Z"},"bugs":{"url":"https://github.com/hubble-ventures/infisicml/issues"},"author":{"name":"Hubble Ventures"},"license":"MIT","homepage":"https://github.com/hubble-ventures/infisicml#readme","keywords":["infisical","secrets","monorepo","dotenv","github-actions","ci","manifest","env"],"repository":{"type":"git","url":"git+https://github.com/hubble-ventures/infisicml.git"},"description":"Declarative Infisical secret manifests for monorepos — pull, validate, and diff per-package secrets, with native GitHub Actions support.","maintainers":[{"name":"anxious-engineer","email":"david@hubble.ventures"}],"readme":"# infisicml\n\nDeclarative [Infisical](https://infisical.com) secret manifests for monorepos.\nEach package declares the secrets it needs in a `secrets.yaml`; infisicml can\nthen **pull** them, **validate** them, and **diff** the secret surface between\ntwo revisions — with native GitHub Actions support.\n\n```yaml\n# apps/payments/secrets.yaml\nversion: 1\nproject: acme-payments\nsecrets:\n  - path: /payments/stripe\n    keys:\n      - STRIPE_SECRET_KEY\n      - STRIPE_WEBHOOK_SECRET: WEBHOOK_SECRET # alias source → target\n  - path: /shared\n    keys:\n      - DATABASE_URL\n```\n\n## Why\n\n| Problem | Without infisicml | With infisicml |\n| --- | --- | --- |\n| Each app needs a different slice of the vault | Hand-written export commands per app × folder | One committed `secrets.yaml` per package, auto-discovered |\n| \"Does this app declare a secret it can't get?\" | Find out when it crashes at runtime | `infisicml validate --against-vault` in CI |\n| \"What secrets does this PR add?\" | Read the diff by eye, hope you catch it | `infisicml diff` posts the delta on the PR |\n\n## How it works\n\nA manifest compiles **once** into a flat, sorted list of _bindings_\n(`path → sourceKey → targetVar`). Every capability is a pure function over that\nlist:\n\n- **pull** fetches values for the bindings and writes a `.env` file (or exports\n  to the job env in CI).\n- **validate** checks the bindings — structurally, then against the live vault.\n- **diff** set-diffs two binding lists.\n\n`diff` and tier-1 `validate` operate on _declarations only_ — no vault access at\nall — so they're fast, offline, and safe to run on untrusted PR branches. The\nvault tiers (`--against-vault`, `--check-values`) query Infisical and should run\nin a trusted context.\n\n## The three capabilities\n\n### 1. Pull\n\n```bash\ninfisicml pull                 # all discovered manifests\ninfisicml pull apps/payments   # one package, by id (its dir relative to root)\ninfisicml pull --env production --profile deploy\n```\n\nReads each folder once (whole-folder, or only the declared keys with\n`fetch: keys`), applies aliases, and writes the resolved values to\n`defaults.output` (default `.env.secrets`) next to each manifest. A missing\nrequired key fails the pull; mark expected-absent keys under\n`environments.<env>.optional`.\n\n### 2. Validate\n\nThree escalating tiers:\n\n```bash\ninfisicml validate                  # tier 1 — schema + structure (no network)\ninfisicml validate --against-vault  # + tier 2 — every declared key exists in the vault\ninfisicml validate --check-values   # + tier 3 — present-but-empty required keys\n```\n\n- **Tier 1** (offline): valid schema, alias syntax, path format, and — the check\n  a plain schema misses — **no two keys resolving to the same variable**.\n- **Tier 2**: declared keys must exist in the vault; undeclared vault keys are\n  reported as drift warnings.\n- **Tier 3**: a required key that exists but is empty is an error.\n\n### 3. Diff\n\n```bash\ninfisicml diff --base origin/main\n```\n\nStructural delta of the secret surface between the working tree and a git ref —\nadded / removed variables and moved sources. Exits non-zero when anything\nchanged (use `--exit-zero` for an informational run). Ideal for gating PRs.\n\n## Install\n\n```bash\npnpm add -D @hubble-ventures/infisicml   # or npm i -D / yarn add -D\n```\n\nRequires Node ≥ 22 (built and tested on the two most recent LTS lines, 22 and\n24). For local use, authenticate with an Infisical token:\n\n```bash\nexport INFISICAL_TOKEN=...            # a machine-identity or user token\nexport INFISICAL_API_URL=...          # optional, defaults to https://app.infisical.com\ninfisicml pull\n```\n\n## GitHub Actions\n\nThe action authenticates with **GitHub OIDC** — no long-lived credential in the\nrepo. The calling job sets `permissions: id-token: write`, and an Infisical\nmachine identity is bound to the GitHub OIDC auth method.\n\n### Pull secrets into the job\n\n```yaml\npermissions:\n  id-token: write\n  contents: read\nsteps:\n  - uses: actions/checkout@v4\n  - uses: hubble-ventures/infisicml/action@v3\n    with:\n      command: pull\n      environment: production\n      identity-id: ${{ vars.INFISICAL_IDENTITY_ID }}\n  # subsequent steps see the secrets as (masked) env vars\n```\n\n### Validate + diff on every PR\n\n```yaml\npermissions:\n  contents: read\n  pull-requests: write\nsteps:\n  - uses: actions/checkout@v4\n    with: { fetch-depth: 0 } # diff needs the base ref\n  - uses: hubble-ventures/infisicml/action@v3\n    with: { command: validate }\n  - uses: hubble-ventures/infisicml/action@v3\n    with:\n      command: diff\n      base: ${{ github.event.pull_request.base.ref }}\n      comment: true # sticky PR comment with the delta\n      fail-on-change: true # require review when the surface changes\n```\n\nSee [`examples/`](examples) for a full manifest and workflow.\n\n## Migrating from v2\n\nv2 used a nested folder tree; v3 uses flat `{ path, keys }` blocks. A codemod\nconverts manifests in place:\n\n```bash\ninfisicml migrate --project <slug>           # dry run — preview the v3 YAML\ninfisicml migrate --project <slug> --write    # apply\n```\n\nIt flattens the tree, preserves aliases, moves `output`/`fetch` under `defaults`,\nrenames `optionalKeys` → `optional`, and validates the result before writing.\n`project` is passed on the CLI because v2 manifests didn't carry it. The `ci`\nblock has no v3 equivalent and is dropped with a warning.\n\n## Manifest reference\n\n| Field | Meaning |\n| --- | --- |\n| `version` | Manifest format version (`1`). |\n| `project` | Infisical project slug the secrets live in. |\n| `defaults.environment` | Default environment (else `development`). |\n| `defaults.output` | Output filename, bare (default `.env.secrets`), written next to the manifest. |\n| `defaults.fetch` | `folder` (whole-folder read + local select) or `keys` (per-key least-privilege read). |\n| `secrets[]` | Ordered `{ path, keys }` blocks. A key is a bare name or a single-pair `{ SOURCE: TARGET }` alias. |\n| `profiles.<name>` | Alternate `secrets`/`fetch` selected with `--profile`. |\n| `environments.<env>.optional` | Keys allowed to be absent in that environment. |\n\nA JSON Schema is published at\n[`@hubble-ventures/infisicml/schema`](schema/secrets.schema.json); reference it\nfrom a manifest for editor autocomplete:\n\n```yaml\n# yaml-language-server: $schema=https://unpkg.com/@hubble-ventures/infisicml/schema/secrets.schema.json\n```\n\n## Library\n\nThe core and adapters are exported for embedding:\n\n```ts\nimport {\n  compile,\n  diffCompiled,\n  validateStructure,\n  InfisicalProvider,\n} from \"@hubble-ventures/infisicml\";\n```\n\n## Architecture\n\n```\nsrc/\n  core/       schema · compile (IR) · materialize · validate · diff   (pure, no I/O)\n  adapters/   infisical (OIDC + fetch) · workspace (fs/git) · gha\n  commands/   resolve · validate · diff                               (shared by CLI + action)\n  cli.ts · action.ts · index.ts\n```\n\nThe pure core holds the logic; adapters are the only place I/O and secret\n_values_ live. That's what keeps `validate`/`diff` value-free and the whole core\nunit-testable without a network.\n\n## Developing\n\n```bash\npnpm install\npnpm check    # gen:schema + typecheck + test + build\npnpm smoke    # build, then exercise the CLI end-to-end offline\n```\n\n`action/index.cjs` (the bundled Action) and `schema/secrets.schema.json` are\ncommitted and verified in CI; run `pnpm build` and commit if you change source.\n\n## Releasing\n\nReleases are automatic: merge a PR that bumps `version` in `package.json` and\nthe release workflow tags it and publishes to npm via **trusted publishing**\n(OIDC, provenance attached) — no `NPM_TOKEN`. It also moves the floating major\ntag (e.g. `v3`) so `hubble-ventures/infisicml/action@v3` tracks the latest.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}