From 4797fe82d26a6e278f573f8ee881e539c6206aa2 Mon Sep 17 00:00:00 2001 From: Toni Bergholm Date: Mon, 13 Jul 2026 16:06:11 +0300 Subject: [PATCH 1/3] =?UTF-8?q?Release=20prep:=20v0.1.0-alpha.1=20?= =?UTF-8?q?=E2=80=94=20versioned,=20publishable=20npm=20packages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - All seven @sentinel/* workspaces at 0.1.0-alpha.1 with exact internal pins, full publish metadata (repository/homepage/bugs/engines/ publishConfig/files allowlists/keywords), per-package README + LICENSE - Fix bin entrypoints: realpath-based guards so `sentinel` works through npm .bin shims and @sentinel/action is import-safe; shebangs for sentinel-mcp and sentinel-ci - ENGINE_VERSION / CLI --version / MCP server version → 0.1.0-alpha.1 - ADR-0052: Landlock helper ships as source only (no prebuilt binary, no postinstall compile); advisory-floor fallback tested on Linux CI; threat model + ARCHITECTURE + CLAUDE.md updated - Release hygiene gate: packages/core/test/package-contents.test.ts (forbidden-file + required-asset assertions per tarball) - scripts/release-smoke.ts: pack + fresh-project install + import/types/ bins/proxy/MCP/steward smoke validation of the packed artifacts - Two-stage release workflow (.github/workflows/release.yml): Stage A build/verify/pack/upload, Stage B publish gated on the protected npm-release environment with checksum/tag/version verification, dependency-order publish --provenance, npm view + clean-install verification, GitHub prerelease last - docs/release-process.md + docs/releases/v0.1.0-alpha.1.md Claude-Session: https://claude.ai/code/session_01LjqCaCwPby6EGi4RmBVtEW --- .github/workflows/release.yml | 241 +++++++++++++++ .gitignore | 3 + ARCHITECTURE.md | 7 +- CLAUDE.md | 11 +- README.md | 8 +- SECURITY.md | 6 +- .../0052-native-helper-release-packaging.md | 105 +++++++ docs/adr/README.md | 1 + docs/release-process.md | 142 +++++++++ docs/releases/v0.1.0-alpha.1.md | 139 +++++++++ package-lock.json | 55 ++-- package.json | 2 +- packages/action/LICENSE | 201 +++++++++++++ packages/action/README.md | 23 ++ packages/action/package.json | 49 +++- packages/action/src/index.ts | 21 +- packages/cli/LICENSE | 201 +++++++++++++ packages/cli/README.md | 27 ++ packages/cli/package.json | 46 ++- packages/cli/src/index.ts | 15 +- packages/core/LICENSE | 201 +++++++++++++ packages/core/README.md | 25 ++ packages/core/package.json | 33 ++- packages/core/src/audit.ts | 2 +- packages/core/test/package-contents.test.ts | 82 ++++++ packages/mcp/LICENSE | 201 +++++++++++++ packages/mcp/README.md | 36 +++ packages/mcp/package.json | 47 ++- packages/mcp/src/index.ts | 3 +- packages/proxy/LICENSE | 201 +++++++++++++ packages/proxy/README.md | 31 ++ packages/proxy/package.json | 45 ++- packages/sandbox/LICENSE | 201 +++++++++++++ packages/sandbox/README.md | 43 +++ packages/sandbox/package.json | 49 +++- packages/sandbox/test/bubblewrap.test.ts | 41 ++- packages/steward/LICENSE | 201 +++++++++++++ packages/steward/README.md | 31 ++ packages/steward/package.json | 43 ++- scripts/release-smoke.ts | 274 ++++++++++++++++++ sentinel-threat-model.md | 13 +- 41 files changed, 3037 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 docs/adr/0052-native-helper-release-packaging.md create mode 100644 docs/release-process.md create mode 100644 docs/releases/v0.1.0-alpha.1.md create mode 100644 packages/action/LICENSE create mode 100644 packages/action/README.md create mode 100644 packages/cli/LICENSE create mode 100644 packages/cli/README.md create mode 100644 packages/core/LICENSE create mode 100644 packages/core/README.md create mode 100644 packages/core/test/package-contents.test.ts create mode 100644 packages/mcp/LICENSE create mode 100644 packages/mcp/README.md create mode 100644 packages/proxy/LICENSE create mode 100644 packages/proxy/README.md create mode 100644 packages/sandbox/LICENSE create mode 100644 packages/sandbox/README.md create mode 100644 packages/steward/LICENSE create mode 100644 packages/steward/README.md create mode 100644 scripts/release-smoke.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e8e55af --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,241 @@ +# Two-stage prerelease pipeline (ADR-0052 era; see docs/release-process.md). +# +# Stage A (test / compat / build-and-verify): runs on manual dispatch or a +# prerelease tag push. Builds once from a clean checkout, runs the full test + +# client-compatibility matrix, packs every workspace, smoke-tests the packed +# artifacts in a fresh project, and uploads immutable tarballs + checksums + +# SBOM + a release manifest. Performs NO publication. +# +# Stage B (publish): runs only on workflow_dispatch with publish=true AND the +# protected `npm-release` environment's approval. Downloads Stage A's exact +# artifacts, verifies checksums / tag / declared versions, refuses to overwrite +# any existing version, publishes in dependency order with provenance, verifies +# via `npm view` + a clean registry install, and only then creates the GitHub +# prerelease. +# +# Auth: prefers npm trusted publishing (GitHub Actions OIDC) — configure it on +# npmjs.com for each package and leave NPM_TOKEN unset; npm ≥11.5 detects it +# automatically. Until then, set the NPM_TOKEN secret ON THE npm-release +# ENVIRONMENT (never repo-wide) so it is unreachable from PR workflows. +name: release + +on: + workflow_dispatch: + inputs: + tag: + description: "Release tag (must already point at this commit for Stage B)" + required: true + default: "v0.1.0-alpha.1" + publish: + description: "Run Stage B (publish to npm + GitHub prerelease)" + type: boolean + default: false + push: + tags: ["v*-alpha*", "v*-beta*", "v*-rc*"] + +permissions: {} + +env: + RELEASE_TAG: ${{ inputs.tag || github.ref_name }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + matrix: + node: ["22", "24"] # Maintenance LTS + Active LTS + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ matrix.node }} + cache: npm + - run: sudo apt-get update && sudo apt-get install -y bubblewrap + - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true # Ubuntu 24.04 userns mitigation; the "no silent skip" test is the real gate + - run: npm ci + - run: npm run build + - run: npm run fixtures + - run: npm run benchmark:publish + - run: npm test + + compat: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "24" + cache: npm + - run: npm ci + - run: npm install --global pnpm@11.11.0 bun@1.3.12 + - run: npm run fixtures + - run: npm run build + - run: npm run compat:clients + - run: npm install --prefix "$RUNNER_TEMP/verdaccio" --ignore-scripts verdaccio@6.7.4 + - run: node --import tsx --test packages/proxy/test/registry-migration.test.ts + env: + SENTINEL_VERDACCIO_BIN: ${{ runner.temp }}/verdaccio/node_modules/.bin/verdaccio + + build-and-verify: + needs: [test, compat] + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "24" + cache: npm + - run: npm ci + - run: npm run build + - name: Pack every workspace and smoke-test the packed artifacts in a fresh project + run: npx tsx scripts/release-smoke.ts --pack-dest release-artifacts --json release-artifacts/smoke-results.json + - name: Verify every tarball declares the release version + run: | + set -euo pipefail + VERSION="${RELEASE_TAG#v}" + for t in release-artifacts/*.tgz; do + declared="$(tar -xzOf "$t" package/package.json | jq -r .version)" + if [ "$declared" != "$VERSION" ]; then + echo "::error::$t declares $declared, expected $VERSION"; exit 1 + fi + done + echo "all tarballs declare $VERSION" + - name: SBOM (CycloneDX, production dependency tree) + run: npm sbom --sbom-format cyclonedx --omit dev > release-artifacts/sbom.cdx.json + - name: Checksums + release manifest + run: | + set -euo pipefail + cd release-artifacts + sha256sum *.tgz > SHA256SUMS + jq -n \ + --arg commit "$GITHUB_SHA" \ + --arg tag "$RELEASE_TAG" \ + --arg run "$GITHUB_RUN_ID" \ + --rawfile sums SHA256SUMS \ + '{commit: $commit, tag: $tag, workflow_run: $run, checksums: $sums}' > release-manifest.json + cat SHA256SUMS release-manifest.json + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: release-artifacts + path: release-artifacts/ + if-no-files-found: error + + publish: + # Stage B: requires BOTH the explicit publish=true dispatch input AND a + # reviewer approving the protected npm-release environment. + if: github.event_name == 'workflow_dispatch' && inputs.publish + needs: build-and-verify + runs-on: ubuntu-latest + environment: npm-release + permissions: + contents: write # create the GitHub prerelease + id-token: write # npm provenance / trusted publishing (OIDC) + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Verify the tag exists and points at the tested commit + run: | + set -euo pipefail + git fetch origin "refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}" || { + echo "::error::tag ${RELEASE_TAG} not found on origin — push it (pointing at $GITHUB_SHA) before approving Stage B"; exit 1; } + tagged="$(git rev-parse "${RELEASE_TAG}^{commit}")" + if [ "$tagged" != "$GITHUB_SHA" ]; then + echo "::error::tag ${RELEASE_TAG} points at $tagged, but this workflow tested $GITHUB_SHA"; exit 1 + fi + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: release-artifacts + path: release-artifacts/ + - name: Verify checksums and declared versions + run: | + set -euo pipefail + cd release-artifacts + sha256sum -c SHA256SUMS + VERSION="${RELEASE_TAG#v}" + for t in *.tgz; do + declared="$(tar -xzOf "$t" package/package.json | jq -r .version)" + [ "$declared" = "$VERSION" ] || { echo "::error::$t declares $declared, expected $VERSION"; exit 1; } + done + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "24" + registry-url: "https://registry.npmjs.org" + - name: Refuse to republish any existing version + run: | + set -euo pipefail + VERSION="${RELEASE_TAG#v}" + for p in core proxy sandbox mcp steward cli action; do + if npm view "@sentinel/$p@$VERSION" version >/dev/null 2>&1; then + echo "::error::@sentinel/$p@$VERSION already exists on the registry — refusing to continue"; exit 1 + fi + done + echo "no target version exists — safe to publish" + - name: Publish in dependency order (--access public --tag alpha --provenance) + env: + # Empty when npm trusted publishing (OIDC) is configured — preferred. + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + VERSION="${RELEASE_TAG#v}" + published="" + for p in core proxy sandbox mcp steward cli action; do + t="release-artifacts/sentinel-$p-$VERSION.tgz" + echo "publishing @sentinel/$p@$VERSION" + if ! npm publish "$t" --access public --tag alpha --provenance; then + echo "::error::publish of @sentinel/$p failed. Already published (immutable): ${published:-none}. Do NOT unpublish; fix forward."; exit 1 + fi + published="$published @sentinel/$p" + echo "- @sentinel/$p@$VERSION published" >> "$GITHUB_STEP_SUMMARY" + done + - name: Verify every published package via npm view + run: | + set -euo pipefail + VERSION="${RELEASE_TAG#v}" + for p in core proxy sandbox mcp steward cli action; do + for i in 1 2 3 4 5; do + got="$(npm view "@sentinel/$p@$VERSION" version 2>/dev/null || true)" + [ "$got" = "$VERSION" ] && break + sleep 15 + done + [ "$got" = "$VERSION" ] || { echo "::error::@sentinel/$p@$VERSION not visible after publish"; exit 1; } + tag_alpha="$(npm view "@sentinel/$p" dist-tags.alpha)" + [ "$tag_alpha" = "$VERSION" ] || { echo "::error::@sentinel/$p dist-tag alpha is $tag_alpha, expected $VERSION"; exit 1; } + echo "@sentinel/$p@$VERSION visible, dist-tag alpha OK" + done + - name: Install the published packages from the public registry in a clean project + run: | + set -euo pipefail + VERSION="${RELEASE_TAG#v}" + dir="$(mktemp -d)" + cd "$dir" + npm init -y >/dev/null + # retry: registry propagation can lag the view endpoint + for i in 1 2 3 4 5; do + npm install --no-audit --no-fund \ + "@sentinel/core@$VERSION" "@sentinel/proxy@$VERSION" "@sentinel/sandbox@$VERSION" \ + "@sentinel/mcp@$VERSION" "@sentinel/steward@$VERSION" "@sentinel/cli@$VERSION" \ + "@sentinel/action@$VERSION" && break + sleep 20 + done + ./node_modules/.bin/sentinel --version | grep -qx "$VERSION" + node -e "import('@sentinel/core').then(m=>{if(m.ENGINE_VERSION!=='$VERSION')process.exit(1)})" + echo "clean-project registry install OK" + - name: Create the GitHub prerelease (only after npm verification) + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + gh release create "$RELEASE_TAG" \ + --prerelease \ + --verify-tag \ + --title "Sentinel $RELEASE_TAG" \ + --notes-file "docs/releases/${RELEASE_TAG}.md" \ + release-artifacts/*.tgz \ + release-artifacts/SHA256SUMS \ + release-artifacts/sbom.cdx.json \ + release-artifacts/release-manifest.json diff --git a/.gitignore b/.gitignore index 1b92bf1..737c2ff 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ policy/keys/ # macOS .DS_Store **/.DS_Store + +# missing-Landlock-helper test scratch (packages/sandbox) +.nohelper-*/ diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e73f50b..a09b0f2 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -275,7 +275,12 @@ exists AND `landlock-exec --check` (an ABI probe) exits 0, cached per process; any negative falls back to the Phase 29 advisory floor with a one-time notice, so a Landlock-less or no-`cc` host never regresses. `computeDenySet` gains a `linux-landlock` `execFloorMode` and `classifyViolation` confirms a -floor-outside exec denial as `exec-floor-deny`. The Phase 29 `/dev/null` +floor-outside exec denial as `exec-floor-deny`. The *published* +`@sentinel/sandbox` package ships the helper as source only +(`native/landlock-exec.c` + `scripts/build-native.mjs`) — never a prebuilt +binary and never a `postinstall` compile; a fresh npm install runs this same +advisory fallback until the operator explicitly compiles the helper +(ADR-0052). The Phase 29 `/dev/null` carve-out is unchanged and still applies (Landlock is allow-list-only and can't deny a literal under an allowed directory) (ADR-0044). `native` (dlopen/WASM) remains formally advisory-only on both platforms — no path-level primitive diff --git a/CLAUDE.md b/CLAUDE.md index 51794ef..2ce1d4d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -236,7 +236,12 @@ Node 22 needs `--experimental-sqlite`). The Landlock helper (`packages/sandbox/native/landlock-exec.c`) is compiled by `npm run build` (`build-native.mjs`, Linux + `cc` only, no-op elsewhere) — **never** a `postinstall` hook or lazy runtime compile; both would be posture violations for -a tool that guards against exactly that. +a tool that guards against exactly that. The *published* `@sentinel/sandbox` +ships the helper as source only (no prebuilt binary in any tarball — enforced by +`packages/core/test/package-contents.test.ts`); npm installs opt in via an +explicit `node …/scripts/build-native.mjs` (ADR-0052). Releases version all +seven workspaces in lockstep with exact internal pins and publish via the +two-stage `release.yml` (see [docs/release-process.md](./docs/release-process.md)). **Proxy env vars** — all optional, all parsed **fail-closed once at startup** (malformed ⇒ FATAL); unset ⇒ documented default, zero behavior change: @@ -258,8 +263,8 @@ a tool that guards against exactly that. ```bash npm run build # tsc --build (project references) + the Linux-only native helper step -npm test # hermetic engine + e2e proxy suite. 990 tests on this darwin host - # as of 2026-07-13 (987 pass, 3 skipped) — but NEVER plan arithmetic +npm test # hermetic engine + e2e proxy suite. 997 tests on this darwin host + # as of 2026-07-13 (994 pass, 3 skipped) — but NEVER plan arithmetic # on a written count; run npm test and use what it prints. npm run demo # offline malware-detection walkthrough node packages/proxy/dist/index.js # run the proxy (see README for env vars) diff --git a/README.md b/README.md index 45b2562..cc842fa 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,12 @@ end-to-end and are covered by the full test suite (Linux CI on Node 22 and 24; macOS Seatbelt enforcement is exercised on maintainers' machines) — but this has not yet been hardened by production use, and APIs may change without notice. The complete phase-by-phase build log lives in -[docs/adr/](./docs/adr/) (one ADR per phase). **No npm packages are -published yet**: build from source (Quickstart below). Threat model: +[docs/adr/](./docs/adr/) (one ADR per phase). **Published as an alpha +preview**: all seven packages ship as `0.1.0-alpha.1` under the `alpha` +dist-tag (`npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha`) — see +the [release notes](./docs/releases/v0.1.0-alpha.1.md) and +[release process](./docs/release-process.md); building from source +(Quickstart below) remains fully supported. Threat model: [sentinel-threat-model.md](./sentinel-threat-model.md) · Homepage: [git-agentic.com/sentinel](https://git-agentic.com/sentinel) diff --git a/SECURITY.md b/SECURITY.md index bd5b14e..aa16871 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,8 +5,10 @@ sandbox for the npm ecosystem. We treat reports against it accordingly. ## Supported versions -Sentinel is pre-1.0. Only the tip of `main` is supported; there are no -maintained release branches and no published npm packages yet. +Sentinel is pre-1.0. Only the tip of `main` and the most recent published +prerelease (`@sentinel/*@alpha`, currently `0.1.0-alpha.1`) are supported; +there are no maintained release branches. Prereleases are snapshots of +`main` — fixes ship as the next prerelease, never as patches to an old one. ## Reporting a vulnerability diff --git a/docs/adr/0052-native-helper-release-packaging.md b/docs/adr/0052-native-helper-release-packaging.md new file mode 100644 index 0000000..2134dc9 --- /dev/null +++ b/docs/adr/0052-native-helper-release-packaging.md @@ -0,0 +1,105 @@ +# ADR-0052: Landlock helper release packaging — source-only, explicit opt-in build, honest advisory fallback + +**Status:** Accepted +**Date:** 2026-07-13 + +Extends ADR-0044 (Landlock exec floor — from-source helper, fail-open +pre-checked detection). Supersedes nothing. + +## Context + +`v0.1.0-alpha.1` is Sentinel's first npm publication. Every package ships as a +built artifact — except one file that cannot be treated like compiled +JavaScript: the Linux Landlock helper (`packages/sandbox/native/landlock-exec.c`), +compiled by `npm run build` (`scripts/build-native.mjs`) into +`dist/landlock-exec`. In the monorepo that is fine — the operator builds on the +machine that runs it. A published npm tarball breaks that assumption three +ways: + +1. A binary compiled on the packing machine (a CI runner, or a maintainer's + laptop) is architecture- and libc-specific. Shipping a Linux x64 binary as + `dist/landlock-exec` would silently present it as portable to arm64/musl + hosts, where it would fail `--check` and fall back — at best dead weight, at + worst a supply-chain-shaped artifact nobody can reproduce from the tarball. +2. Compiling at install time via a lifecycle script is a **posture violation**: + Sentinel's entire premise is that install-time script execution is the + attack surface. `build-native.mjs`'s own header records this constraint + (deliberately a build step, never a postinstall hook), and CLAUDE.md pins + it as a stack rule. +3. Downloading a prebuilt binary at install or first-run time would put an + unauditable network fetch inside the trust boundary — worse than either. + +ADR-0044 already designed for helper absence: detection is fail-open and +pre-checked (`landlock-exec --check` ABI probe, cached), and a missing or +non-working helper falls back to the Phase 29 advisory floor with a one-time +stderr notice, with filesystem/network/env containment and the `/dev/null` +exfil-tool carve-out unaffected. + +## Decision + +For `0.1.0-alpha.1`, `@sentinel/sandbox` ships the helper **as source only**, +with an explicit, operator-invoked build path and the documented advisory +fallback: + +1. **The tarball never contains a compiled helper.** The `files` allowlist + excludes `dist/landlock-exec` explicitly, and the release-hygiene test + (`packages/core/test/package-contents.test.ts`) fails the suite if a + compiled helper ever enters a packed tarball — so a Linux-built release + pipeline cannot ship one accidentally. +2. **The tarball contains the source and the build script**: + `native/landlock-exec.c` (self-contained, no kernel headers needed) and + `scripts/build-native.mjs`. Both are first-party, reviewed files — the same + from-source posture ADR-0044 chose over prebuilt distribution. +3. **Compilation is an explicit operator action, never a lifecycle script.** + `node node_modules/@sentinel/sandbox/scripts/build-native.mjs` compiles the + helper in place (Linux + `cc` only; a no-op elsewhere). There is no + `postinstall`, no lazy runtime compile, and no network fetch. The package + README documents the command and the trade-off. +4. **Default behavior on Linux is the advisory exec floor, stated honestly.** + Fresh installs run without the helper: the pre-checked detection finds no + binary and prints the one-time notice ("Landlock exec floor unavailable on + this host — advisory floor active…"). Filesystem/network/env containment, + the `SENSITIVE_EXECUTABLES` `/dev/null` carve-out, and violation telemetry + are unaffected — the same fallback ADR-0044 shipped for Landlock-less + kernels and no-`cc` hosts, now also the packaged-artifact default. +5. **macOS Seatbelt is untouched.** Seatbelt enforcement involves no native + compilation; the darwin exec floor (ADR-0042) ships fully enforced. +6. **The missing-helper state is tested as shipped.** A Linux CI test copies + the built `dist/` without the helper binary and asserts: scripts still run, + the advisory notice prints exactly once per process, and containment is + unchanged (`packages/sandbox/test/bubblewrap.test.ts`). + +## Alternatives considered + +- **Architecture-specific optional packages (`@sentinel/landlock-linux-x64`, + … via `optionalDependencies` + `os`/`cpu`, the esbuild/swc pattern).** The + strongest end-state — prebuilt, reproducible, no toolchain requirement — and + the likely post-alpha direction. Rejected *for the alpha*: it multiplies the + publish surface (per-arch packages, per-arch CI builders, provenance for + each) before the first release has shipped at all, and a security product + distributing opaque prebuilt binaries needs reproducible-build + infrastructure (pinned toolchain, verifiable digests) that does not exist + yet. Shipping it half-done would be worse than the honest fallback. +- **`postinstall` compilation.** Rejected outright — the posture violation + named in Context; this is the exact class of behavior Sentinel flags in + other packages (`install-scripts` rule). +- **Shipping the pack-machine's binary in the tarball.** Rejected — a Linux + x64 artifact silently presented as portable, unreproducible from the + tarball, and a standing temptation for the release pipeline to become a + binary-injection point. +- **Blocking publication of `@sentinel/sandbox` (and its dependents).** + Unnecessary — ADR-0044's fallback is a designed, tested, honest degradation, + not a silent weakening: the notice states the exact residual (a dropped + binary can exec but stays filesystem+network confined), and the enforced + floor is one documented command away on hosts that want it. + +## Consequences + +- Linux exec-floor enforcement is **opt-in** for npm-installed alphas + (explicit compile) instead of automatic — the price of refusing both + lifecycle-script compilation and fake-portable binaries. Monorepo builds + (`npm run build`) are unchanged. +- The threat model's "Landlock + from-source helper where available" caveat + now has a distribution-channel dimension, recorded there (§3.9, §4). +- Publishing per-arch optional helper packages is the recorded follow-up for + a later release, gated on reproducible-build infrastructure. diff --git a/docs/adr/README.md b/docs/adr/README.md index f985cbb..3963f0a 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -145,6 +145,7 @@ first shipped slice; Phases 31 and 32 complete claiming and retraction. | ADR | Title | Decision in one line | |-----|-------|----------------------| | [0051](./0051-sandboxed-exec.md) | Sandboxed `sentinel exec` | `Sandbox.runArgv` (no-shell, execFile-style) + `sentinel exec -- ` reuse the approved-capability model, scrubbed env, and violation telemetry to contain Sentinel-mediated command execution; scoped to explicit invocations only — raw `require()`/`npx` outside it stay uncontained, defense-in-depth behind the ADR-0049 registry gate | +| [0052](./0052-native-helper-release-packaging.md) | Landlock helper release packaging | The published `@sentinel/sandbox` ships the helper as source only (`native/landlock-exec.c` + `build-native.mjs`) — never a prebuilt binary, never a `postinstall` compile; fresh Linux installs run the documented advisory exec floor with a one-time notice until the operator explicitly compiles the helper; enforced by the package-contents test and a missing-helper CI test | ## Conventions diff --git a/docs/release-process.md b/docs/release-process.md new file mode 100644 index 0000000..53ca530 --- /dev/null +++ b/docs/release-process.md @@ -0,0 +1,142 @@ +# Sentinel release process + +How Sentinel versions, packages, and publishes its npm packages. The +two-stage automation lives in +[`.github/workflows/release.yml`](../.github/workflows/release.yml); the +native-helper packaging decision is [ADR-0052](./adr/0052-native-helper-release-packaging.md). + +## Packages and publication order + +Seven workspaces publish under the `@sentinel` scope; the root +`sentinel-registry` package is `private` and never publishes. Publication +must follow the internal dependency graph: + +1. `@sentinel/core` +2. `@sentinel/proxy`, `@sentinel/sandbox`, `@sentinel/mcp`, `@sentinel/steward` +3. `@sentinel/cli` (depends on core + sandbox) +4. `@sentinel/action` (depends on core + proxy) + +The release workflow publishes in exactly this order and stops at the first +failure without unpublishing anything already released. + +## Prerelease versioning + +- Pre-1.0 releases use `0.1.0-alpha.N` (then `-beta.N`, `-rc.N`) with the + npm dist-tag matching the prerelease channel (`alpha`, `beta`, `rc`). + `latest` is **never** pointed at a prerelease. +- All seven packages version in lockstep — one release version across the + workspace, even for packages with no changes. Lockstep keeps the internal + dependency pins trivially correct and the support matrix one-dimensional. +- Internal dependencies are pinned **exact** (`"@sentinel/core": "0.1.0-alpha.1"`, + no `^`/`~`, never `workspace:*` or `file:` in a published manifest). A + prerelease must never float onto a different prerelease. +- User-visible hardcoded versions move with the release: + `ENGINE_VERSION` (`packages/core/src/audit.ts`), the MCP server version + (`packages/mcp/src/index.ts`), and the CLI `--version` + (`packages/cli/src/index.ts`). + +## Dependency update policy + +- Third-party runtime dependencies use caret ranges pinned by + `package-lock.json`; `npm ci` + the lockfile are the reproducibility + boundary. Majors are not bumped without review (CLAUDE.md stack rules). +- GitHub Actions are pinned to full commit SHAs with a version comment; + Dependabot raises SHA-pinned bumps (CONTRIBUTING.md). + +## Release gate (what must be green) + +`npm ci`, `npm run build`, `npm run typecheck`, `npm run fixtures`, +`npm test` (no weakened/skipped tests to make a release pass — the +package-contents test in `packages/core/test/package-contents.test.ts` is +part of the suite and gates tarball hygiene), `npm run benchmark:publish`, +`npm run compat:clients`, `npm audit --omit=dev`, a secret scan over history +and worktree, a dependency license scan, and +`npx tsx scripts/release-smoke.ts` (packs every workspace and validates the +packed artifacts in a fresh project: imports, types, every bin, proxy/MCP/ +steward startup). + +## Two-stage automation + +**Stage A — build and verify** (`test`/`compat`/`build-and-verify` jobs): +manual dispatch or a prerelease tag push. Pinned action SHAs, Node 22 + 24 +test matrix, one clean-checkout build, pack, packed-artifact smoke test, and +an uploaded artifact set: tarballs, `SHA256SUMS`, CycloneDX SBOM, +`release-manifest.json`, smoke results. No publication. + +**Stage B — publish** (`publish` job): requires `publish=true` on the +dispatch **and** approval of the protected `npm-release` GitHub environment. +It downloads Stage A's exact artifacts, verifies checksums, verifies the tag +points at the tested commit, verifies every tarball declares the release +version, refuses to run if any target version already exists, publishes in +dependency order with `--access public --tag alpha --provenance`, verifies +each package via `npm view` (version + dist-tag), installs the published +packages from the public registry in a clean project, and only then creates +the GitHub prerelease with the artifacts attached. + +Least privilege: top-level `permissions: {}`; the publish job alone gets +`contents: write` (release creation) and `id-token: write` (provenance). +`pull_request_target` is never used and no publish credential is reachable +from a PR-triggered workflow. + +## Trusted publishing + +Prefer npm **trusted publishing** (GitHub Actions OIDC) over any long-lived +token: configure the repo/workflow as a trusted publisher for each +`@sentinel/*` package on npmjs.com and leave `NPM_TOKEN` unset — npm ≥ 11.5 +detects OIDC automatically and mints per-publish credentials. Until trusted +publishing is configured (it may not be configurable before a package's +first publish), use a **granular automation token scoped to the @sentinel +packages only**, stored as an **environment secret on `npm-release`** +(never repo-wide), and rotate or revoke it immediately after the release. +`--provenance` works with either auth mode and links each package to the +exact commit + workflow run. + +## Rollback limitations (read before publishing) + +- **npm versions are immutable in practice.** Unpublish is heavily + restricted (72-hour/no-dependents rules) and even when allowed, a + version number is spent forever. Plan on **fix-forward**: publish + `-alpha.N+1`, never reuse a version. +- If a publish fails partway, the already-published packages stay + published. Do **not** unpublish; publish the remaining packages from the + same artifacts once the failure is fixed (the version-exists preflight + skips nothing — a partial release is completed by re-running Stage B + only if no published tarball changed; otherwise bump to the next + prerelease number across the board). +- A Git tag and GitHub release can be deleted, but anyone may already have + fetched them; treat both as public the moment they are pushed. + +## Compromised-release response + +1. **Deprecate immediately**: `npm deprecate @sentinel/

@ + "SECURITY: compromised — do not install"` for every affected package. +2. Point the dist-tag at the last known-good version (`npm dist-tag add + @sentinel/

@ alpha`). +3. Request npm unpublish/security takedown through npm support if within + policy; do not rely on it. +4. Rotate every credential the pipeline touched (npm token, corpus/policy + signing keys if exposure is plausible); revoke the trusted-publisher + config until the workflow is audited. +5. Publish a GitHub security advisory and a fixed release; document the + window and indicators. (Sentinel's own `known-advisory` corpus should + carry the compromised versions in its next regeneration.) + +## Deprecation procedure + +`npm deprecate @ ""` — metadata-only, reversible with +an empty message. Use for: superseded prereleases after a stable release, +and versions with known defects that don't warrant the compromised-release +path. + +## Promoting stable 0.1.0 later + +1. Land fixes on `main`; bump all workspaces + internal pins + + `ENGINE_VERSION`/CLI/MCP versions to `0.1.0` (no prerelease suffix). +2. Run the same two-stage pipeline with tag `v0.1.0`, publishing with + `--tag latest` (the workflow's dist-tag is the one alpha-specific knob to + change — everything else is identical). +3. Keep `alpha` pointing at the last alpha until `latest` exists, then move + `alpha` forward to `0.1.0` as well so `@alpha` installs never resolve + older than stable. +4. The GitHub release loses the `--prerelease` flag; SECURITY.md's supported + versions section starts naming the stable line. diff --git a/docs/releases/v0.1.0-alpha.1.md b/docs/releases/v0.1.0-alpha.1.md new file mode 100644 index 0000000..2a0e04a --- /dev/null +++ b/docs/releases/v0.1.0-alpha.1.md @@ -0,0 +1,139 @@ +# Sentinel v0.1.0-alpha.1 + +> ⚠️ **Alpha, pre-1.0.** This is the first published preview of Sentinel. It +> works end-to-end and is covered by a ~1,000-test suite, but it has **not +> been hardened by production use**. APIs, policy schemas, and wire formats +> may change without notice between prereleases. **Do not treat this release +> as production-ready.** + +Sentinel is an agent-auditable security layer for the npm ecosystem: a +transparent auditing proxy that scores every tarball with a deterministic +engine *before install-time code can run*, an authoritative registry write +path, a deny-by-default install sandbox, and agent-native tooling. + +## Install (alpha dist-tag) + +```bash +# CLI + proxy (most users start here) +npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha + +sentinel-proxy & # transparent auditing proxy on :4873 +sentinel audit is-odd 3.0.1 # pre-install verdict, no code executed +sentinel audit-tree package-lock.json --sbom sbom.json + +# agent hosts (MCP) +npm install -g @sentinel/mcp@alpha + +# library / CI / steward +npm install @sentinel/core@alpha @sentinel/action@alpha @sentinel/steward@alpha +``` + +All seven packages — `@sentinel/core`, `@sentinel/proxy`, +`@sentinel/sandbox`, `@sentinel/cli`, `@sentinel/mcp`, `@sentinel/steward`, +`@sentinel/action` — publish in lockstep as `0.1.0-alpha.1` under the +`alpha` dist-tag, Apache-2.0, Node ≥ 22. + +## What's in this release + +**Deterministic audit engine (`@sentinel/core`).** Ten pure heuristic rules +(install-scripts, secret-exfil, network-egress, obfuscation, provenance, +typosquat, release-anomaly, known-advisory, known-vulnerability CVE ranges, +and the dataflow-correlated `native-payload-loader`), raw-byte magic +classification of every packaged file, decompression-bomb caps, offline +registry-signature and Sigstore-provenance verification bound to the actual +served bytes, npm/yarn/pnpm lockfile parsing, CycloneDX 1.6 SBOM export, and +signed DSSE audit attestations. Same input + same policy ⇒ same score, +always; the optional LLM adapter can only annotate, never set a verdict. + +**Authoritative registry (`@sentinel/proxy`).** A transparent mirror of +public npm (only `dist.tarball` URLs rewritten) plus a native write path: +`npm publish` against Sentinel is audited **synchronously** and gated by +signed policy (`publishGate`, default block) before any byte is served. +Name resolution is a pure partition — policy-private → verified-claim → +public-mirror — so dependency-confusion downgrades are structurally +inexpressible for claimed names. Includes time-locked retraction +(age < 72 h AND downloads < 1,000; tombstones kill availability, never +history), release-cooldown and quarantine serve-time overlays, signed +role-token auth, SSRF origin pinning, byte caps, and opt-in SQLite +history/metrics. + +**Verified namespace steward (`@sentinel/steward`).** Exact-apex DNS TXT +claim challenges, three-tier grandfathering against upstream evidence, +claimant-key-signed transfers with 30-day timelocks, renewal/freeze +lifecycle, and atomic Ed25519-signed claim/retraction corpus releases that +proxies verify fail-closed at boot. + +**npm/pnpm/Yarn Berry/bun compatibility.** Native names speak the npm wire +protocol: full packuments with `time`/`_rev`, corgi Accept negotiation, +dist-tags, legacy login/whoami, and npm's `-rev` unpublish dance mapped onto +time-locked retraction. The compat suite drives the four real client +binaries (install, publish, and every mutation each client exposes) in CI. + +**Capability sandbox (`@sentinel/sandbox`).** Deny-by-default install-time +containment behind one approved-capability model: + +- **macOS (Seatbelt):** fully enforced — write floor, `$HOME` read denial, + env scrubbing, network gating, exec floor with an exfil-tool carve-out + (curl, wget, nc, …). +- **Linux (bubblewrap):** filesystem/network/env containment and the + exfil-tool exec carve-out always enforced. The Landlock **exec floor** + ships **as source only** in this alpha (`native/landlock-exec.c`) — no + prebuilt binary and deliberately no install-time compilation (Sentinel + does not run lifecycle scripts, by posture). Without the compiled helper + the exec floor is **advisory** and announced by a one-time notice; compile + it explicitly with + `node node_modules/@sentinel/sandbox/scripts/build-native.mjs` + (Linux + `cc`). See ADR-0052. +- Any other platform: fail-closed (no sandbox ⇒ enforced operations refuse + to run unsandboxed). + +**CLI (`@sentinel/cli`).** `sentinel audit`/`audit-tree`/`explain`/`scan`, +registry-redirected `install`/`npx`, sandbox-enforced `install --enforce`, +sandboxed one-shot `exec`, policy init/validate/preview/keygen/sign/verify, +token minting, attestations, stats/history. + +**MCP server (`@sentinel/mcp`).** Stdio Model Context Protocol server for +agent hosts: six read tools plus one request-only approval tool — an agent +can ask, only a human can grant. + +**GitHub Action (`@sentinel/action`, bin `sentinel-ci`).** Self-boots the +proxy in-process, audits the lockfile, uploads a CycloneDX SBOM, and posts +an idempotent PR verdict comment. + +## Known limitations + +- **Alpha quality**: no production hardening; expect breaking changes + between prereleases. The `alpha` dist-tag is the only channel. +- **Heuristics are signal, not proof** — false negatives and positives are + expected; Sentinel is defense-in-depth, not a guarantee (threat model §4). +- **Linux Landlock exec floor is opt-in** in this alpha (source-only helper, + above); filesystem/network/env containment does not depend on it. +- **`native` (dlopen/WASM) capability is advisory-only** on both platforms. +- Runtime behavior of installed packages after an `allow` is out of scope — + the sandbox covers lifecycle scripts and `sentinel exec` invocations, not + your application's own imports. +- The bundled typosquat/advisory/CVE corpora are static snapshots that lag + reality between regenerations; wire operator feeds + (`SENTINEL_ADVISORIES`/`SENTINEL_VULNERABILITIES`) for freshness. +- Control-plane reads are open by design; put the proxy behind network + access control if audit history is sensitive. +- SQLite history is single-node; no retention/pruning yet. +- The GitHub Action is not yet on the Marketplace — reference the repo + (`uses: git-agentic/pkg-registry@v0.1.0-alpha.1`). + +## Upgrading and feedback + +Alphas are fix-forward: update with +`npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha` (repeat per +package) — version numbers are never reused. File bugs, detection gaps, and +feature requests at +[github.com/git-agentic/pkg-registry/issues](https://github.com/git-agentic/pkg-registry/issues) +(detection gaps have their own issue template). **Exploitable flaws** — +sandbox escapes, gate bypasses, fail-open scoring, auth bypasses, SSRF — go +through [private vulnerability reporting](https://github.com/git-agentic/pkg-registry/security), +not public issues (see SECURITY.md). + +Full documentation: [README](https://github.com/git-agentic/pkg-registry#readme) · +[ARCHITECTURE](https://github.com/git-agentic/pkg-registry/blob/main/ARCHITECTURE.md) · +[threat model](https://github.com/git-agentic/pkg-registry/blob/main/sentinel-threat-model.md) · +[release process](https://github.com/git-agentic/pkg-registry/blob/main/docs/release-process.md) diff --git a/package-lock.json b/package-lock.json index 08322a8..36f671b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sentinel-registry", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sentinel-registry", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "workspaces": [ "packages/core", @@ -2025,26 +2025,29 @@ }, "packages/action": { "name": "@sentinel/action", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0", - "@sentinel/proxy": "0.1.0" + "@sentinel/core": "0.1.0-alpha.1", + "@sentinel/proxy": "0.1.0-alpha.1" }, "bin": { "sentinel-ci": "dist/index.js" }, "devDependencies": { "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } }, "packages/cli": { "name": "@sentinel/cli", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0", - "@sentinel/sandbox": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", + "@sentinel/sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, "bin": { @@ -2053,11 +2056,14 @@ }, "devDependencies": { "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } }, "packages/core": { "name": "@sentinel/core", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", @@ -2072,15 +2078,18 @@ "devDependencies": { "@types/node": "^24.13.2", "@types/semver": "^7.7.0" + }, + "engines": { + "node": ">=22" } }, "packages/mcp": { "name": "@sentinel/mcp", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "zod": "^3.23.8" }, "bin": { @@ -2088,14 +2097,17 @@ }, "devDependencies": { "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } }, "packages/proxy": { "name": "@sentinel/proxy", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" @@ -2107,25 +2119,31 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } }, "packages/sandbox": { "name": "@sentinel/sandbox", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0" + "@sentinel/core": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } }, "packages/steward": { "name": "@sentinel/steward", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, @@ -2135,6 +2153,9 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^24.13.2" + }, + "engines": { + "node": ">=22" } } } diff --git a/package.json b/package.json index 884a5de..3bfea44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sentinel-registry", - "version": "0.1.0", + "version": "0.1.0-alpha.1", "private": true, "description": "Sentinel — an agent-auditable security/audit proxy for the npm ecosystem (Phase 1 wedge).", "license": "Apache-2.0", diff --git a/packages/action/LICENSE b/packages/action/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/action/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/action/README.md b/packages/action/README.md new file mode 100644 index 0000000..b45d68b --- /dev/null +++ b/packages/action/README.md @@ -0,0 +1,23 @@ +# @sentinel/action + +`sentinel-ci`: a self-contained CI runner for GitHub Actions. It boots the +Sentinel proxy in-process against real npm, audits your lockfile, writes a +CycloneDX SBOM, emits GitHub-native outputs/annotations, and renders an +idempotent PR comment body — no separately-running proxy needed. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install @sentinel/action@alpha +``` + +This package is the engine behind the composite GitHub Action defined at the +root of the [Sentinel repository](https://github.com/git-agentic/pkg-registry) +(`action.yml`). It is driven by `INPUT_*` environment variables +(`INPUT_LOCKFILE`, `INPUT_POLICY`, `INPUT_SBOM_PATH`, `INPUT_FAIL_ON`, +`INPUT_OMIT_DEV`, `INPUT_WORKING_DIRECTORY`) matching the action's inputs. + +## License + +Apache-2.0 diff --git a/packages/action/package.json b/packages/action/package.json index a7d7ed9..b96ce6d 100644 --- a/packages/action/package.json +++ b/packages/action/package.json @@ -1,14 +1,51 @@ { "name": "@sentinel/action", - "version": "0.1.0", - "description": "Sentinel CI runner: self-booting dependency-tree audit for GitHub Actions (sentinel-ci).", + "version": "0.1.0-alpha.1", + "description": "Sentinel CI runner: self-booting dependency-tree audit for GitHub Actions (sentinel-ci) — audits a lockfile, writes a CycloneDX SBOM, and posts a PR verdict.", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/action" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", - "bin": { "sentinel-ci": "./dist/index.js" }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "bin": { + "sentinel-ci": "./dist/index.js" + }, + "files": [ + "dist", + "!dist/**/*.map" + ], + "keywords": [ + "security", + "supply-chain", + "github-actions", + "ci", + "npm-audit", + "sbom" + ], "dependencies": { - "@sentinel/core": "0.1.0", - "@sentinel/proxy": "0.1.0" + "@sentinel/core": "0.1.0-alpha.1", + "@sentinel/proxy": "0.1.0-alpha.1" }, - "devDependencies": { "@types/node": "^24.13.2" } + "devDependencies": { + "@types/node": "^24.13.2" + } } diff --git a/packages/action/src/index.ts b/packages/action/src/index.ts index 54db1db..e519057 100644 --- a/packages/action/src/index.ts +++ b/packages/action/src/index.ts @@ -1,4 +1,6 @@ -import { readFileSync } from "node:fs"; +#!/usr/bin/env node +import { readFileSync, realpathSync } from "node:fs"; +import { pathToFileURL } from "node:url"; import { NpmUpstream, LocalFixtureUpstream, type Upstream } from "@sentinel/proxy"; import { loadPolicy, DEFAULT_POLICY, type EnterprisePolicy } from "@sentinel/core"; import { runCi } from "./run.js"; @@ -44,7 +46,16 @@ async function main(): Promise { process.exit(result.exitCode); } -main().catch((err) => { - console.error(`::error::sentinel-ci failed: ${(err as Error).message}`); - process.exit(1); -}); +// Run only when invoked as the entrypoint (bin shim or `node dist/index.js`), +// never on import — the same guard as @sentinel/proxy and @sentinel/mcp. +function isEntrypoint(): boolean { + const arg = process.argv[1]; + if (!arg) return false; + try { return import.meta.url === pathToFileURL(realpathSync(arg)).href; } catch { return false; } +} +if (isEntrypoint()) { + main().catch((err) => { + console.error(`::error::sentinel-ci failed: ${(err as Error).message}`); + process.exit(1); + }); +} diff --git a/packages/cli/LICENSE b/packages/cli/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/cli/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 0000000..c096c5c --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,27 @@ +# @sentinel/cli + +The Sentinel CLI: pre-install audit verdicts (`sentinel audit`), whole-tree +lockfile audits with SBOM export (`sentinel audit-tree`), registry-redirected +installs (`sentinel install`, `sentinel npx`), sandbox-enforced installs +(`--enforce`), sandboxed one-shot commands (`sentinel exec`), policy +authoring/signing, and signed audit attestations. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install -g @sentinel/cli@alpha + +sentinel --version +sentinel audit is-odd 3.0.1 # requires a running @sentinel/proxy +sentinel audit-tree package-lock.json +``` + +Most commands talk to a running [`@sentinel/proxy`](https://www.npmjs.com/package/@sentinel/proxy) +(default `http://localhost:4873`, override with `SENTINEL_PROXY` or `-p`). +See the [Sentinel repository](https://github.com/git-agentic/pkg-registry) +for the full command reference. + +## License + +Apache-2.0 diff --git a/packages/cli/package.json b/packages/cli/package.json index a9e4cb1..2a04827 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,18 +1,54 @@ { "name": "@sentinel/cli", - "version": "0.1.0", - "description": "Sentinel CLI: pre-install audit verdicts and registry-redirected npm/npx.", + "version": "0.1.0-alpha.1", + "description": "Sentinel CLI: pre-install audit verdicts, whole-tree lockfile audits, registry-redirected npm/npx, policy tooling, and sandbox-enforced installs.", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/cli" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, "bin": { "sentinel": "./dist/index.js", "sentinel-script-shell": "./dist/script-shell.js" }, + "files": [ + "dist", + "!dist/**/*.map" + ], + "keywords": [ + "security", + "supply-chain", + "npm-audit", + "cli", + "sbom", + "attestation", + "sandbox" + ], "dependencies": { - "@sentinel/core": "0.1.0", - "@sentinel/sandbox": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", + "@sentinel/sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, - "devDependencies": { "@types/node": "^24.13.2" } + "devDependencies": { + "@types/node": "^24.13.2" + } } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index b256bc8..76a2e77 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node import { Buffer } from "node:buffer"; -import { lstatSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; +import { lstatSync, readdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { join, relative, basename } from "node:path"; import { spawn } from "node:child_process"; @@ -28,7 +28,7 @@ const program = new Command(); program .name("sentinel") .description("Agent-auditable security layer for npm — pre-install audit verdicts.") - .version("0.1.0"); + .version("0.1.0-alpha.1"); program .command("audit") @@ -559,7 +559,16 @@ program process.exitCode = r.exitCode; }); -if (process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("index.js")) program.parseAsync(); +// Parse when invoked as the entrypoint — including through an npm .bin shim, +// which is a symlink whose own name ("sentinel") never matches this file's; +// realpathSync resolves it back to dist/index.js. +function isCliEntrypoint(): boolean { + const arg = process.argv[1]; + if (!arg) return false; + if (arg.endsWith("index.ts") || arg.endsWith("index.js")) return true; + try { return realpathSync(arg).endsWith("index.js"); } catch { return false; } +} +if (isCliEntrypoint()) program.parseAsync(); // --------------------------------------------------------------------------- diff --git a/packages/core/LICENSE b/packages/core/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/core/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/core/README.md b/packages/core/README.md new file mode 100644 index 0000000..7b90743 --- /dev/null +++ b/packages/core/README.md @@ -0,0 +1,25 @@ +# @sentinel/core + +The Sentinel audit engine: deterministic heuristic rules, scoring, the audit +data model, multi-format lockfile parsing (npm/yarn/pnpm), CycloneDX 1.6 SBOM +export, signed policy and attestation primitives, and a pluggable LLM adapter +that can only ever *enrich* — never set — a score. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install @sentinel/core@alpha +``` + +```ts +import { runAudit, score, DEFAULT_POLICY } from "@sentinel/core"; +``` + +The engine is fully offline and deterministic: same input + same policy ⇒ same +score, always. See the [Sentinel repository](https://github.com/git-agentic/pkg-registry) +for the full documentation, architecture, and threat model. + +## License + +Apache-2.0 diff --git a/packages/core/package.json b/packages/core/package.json index e4fdbbe..8060e6c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,9 +1,23 @@ { "name": "@sentinel/core", - "version": "0.1.0", - "description": "Sentinel audit engine: deterministic heuristic rules, scoring, data model, and pluggable LLM adapter.", + "version": "0.1.0-alpha.1", + "description": "Sentinel audit engine: deterministic heuristic rules, scoring, data model, lockfile parsing, SBOM export, and pluggable LLM adapter.", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/core" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { @@ -12,6 +26,21 @@ "default": "./dist/index.js" } }, + "files": [ + "dist", + "!dist/**/*.map", + "trust" + ], + "keywords": [ + "security", + "supply-chain", + "npm-audit", + "malware-detection", + "static-analysis", + "sbom", + "provenance", + "sigstore" + ], "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/protobuf-specs": "^0.5.1", diff --git a/packages/core/src/audit.ts b/packages/core/src/audit.ts index 73b4e7a..a8231a6 100644 --- a/packages/core/src/audit.ts +++ b/packages/core/src/audit.ts @@ -21,7 +21,7 @@ import type { import type { Advisory } from "./advisory-corpus.js"; import type { VulnAdvisory } from "./vuln-corpus.js"; -export const ENGINE_VERSION = "0.1.0"; +export const ENGINE_VERSION = "0.1.0-alpha.1"; /** Run the heuristic rule pipeline over an already-extracted package. */ export function runRules(input: AuditInput): Finding[] { diff --git a/packages/core/test/package-contents.test.ts b/packages/core/test/package-contents.test.ts new file mode 100644 index 0000000..a8c192d --- /dev/null +++ b/packages/core/test/package-contents.test.ts @@ -0,0 +1,82 @@ +// Release-hygiene gate: every publishable workspace tarball must contain ONLY +// runtime files. This test runs `npm pack --dry-run --json` per workspace and +// fails if a forbidden file (tests, fixtures, keys, env files, source maps, +// compiled native binaries, internal docs, ...) would enter a published +// tarball, or if a required runtime asset is missing. +// +// Requires `npm run build` to have produced dist/ (CI builds before testing). +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { execFileSync } from "node:child_process"; +import { existsSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..", "..", ".."); + +const WORKSPACES = ["core", "proxy", "sandbox", "cli", "mcp", "action", "steward"] as const; + +/** Path patterns that must never appear in a published tarball. */ +const FORBIDDEN: { name: string; re: RegExp }[] = [ + { name: "test files", re: /(^|\/)test(s)?\/|\.test\./ }, + { name: "fixtures", re: /(^|\/)fixtures\// }, + { name: "TypeScript sources", re: /^src\// }, + { name: "source maps", re: /\.map$/ }, + { name: "tsbuildinfo", re: /\.tsbuildinfo$/ }, + { name: "private keys / PEM material", re: /\.(pem|key)$|\.key\.|private.*key/i }, + { name: "env files", re: /(^|\/)\.env(\.|$)/ }, + { name: "databases", re: /\.(db|sqlite3?)$/ }, + { name: "git metadata", re: /(^|\/)\.git(\/|$|ignore$|attributes$)/ }, + { name: "node_modules", re: /(^|\/)node_modules\// }, + { name: "coverage output", re: /(^|\/)coverage\// }, + { name: "OS junk", re: /\.DS_Store$/ }, + { name: "compiled landlock helper (must never ship prebuilt)", re: /^dist\/landlock-exec$/ }, + { name: "tsconfig", re: /tsconfig.*\.json$/ }, + { name: "agent/internal docs", re: /(^|\/)(CLAUDE|AGENTS)\.md$|\.superpowers\// }, + { name: "local stores", re: /\.sentinel-store\.json$|sentinel-history/ }, +]; + +/** Per-workspace runtime assets that MUST be present. */ +const REQUIRED: Record<(typeof WORKSPACES)[number], string[]> = { + core: ["dist/index.js", "dist/index.d.ts", "trust/trusted-root.json", "trust/npm-attestation-keys.json", "LICENSE", "README.md", "package.json"], + proxy: ["dist/index.js", "dist/registry-cli.js", "dist/server.js", "public/index.html", "LICENSE", "README.md", "package.json"], + sandbox: ["dist/index.js", "native/landlock-exec.c", "scripts/build-native.mjs", "LICENSE", "README.md", "package.json"], + cli: ["dist/index.js", "dist/script-shell.js", "LICENSE", "README.md", "package.json"], + mcp: ["dist/index.js", "LICENSE", "README.md", "package.json"], + action: ["dist/index.js", "LICENSE", "README.md", "package.json"], + steward: ["dist/index.js", "LICENSE", "README.md", "package.json"], +}; + +function packList(pkgDir: string): string[] { + const out = execFileSync("npm", ["pack", "--dry-run", "--json"], { + cwd: pkgDir, + encoding: "utf8", + // npm pack --dry-run writes the JSON report to stdout and progress to stderr + stdio: ["ignore", "pipe", "ignore"], + }); + const parsed = JSON.parse(out) as [{ files: { path: string }[] }]; + return parsed[0].files.map((f) => f.path); +} + +for (const ws of WORKSPACES) { + test(`@sentinel/${ws} tarball contains only runtime files`, () => { + const pkgDir = join(repoRoot, "packages", ws); + assert.ok( + existsSync(join(pkgDir, "dist", "index.js")), + `packages/${ws}/dist missing — run \`npm run build\` before the package-contents test`, + ); + const files = packList(pkgDir); + + const violations: string[] = []; + for (const f of files) { + for (const { name, re } of FORBIDDEN) { + if (re.test(f)) violations.push(`${f} (${name})`); + } + } + assert.deepEqual(violations, [], `forbidden files in @sentinel/${ws} tarball:\n ${violations.join("\n ")}`); + + for (const req of REQUIRED[ws]) { + assert.ok(files.includes(req), `@sentinel/${ws} tarball is missing required runtime file: ${req}`); + } + }); +} diff --git a/packages/mcp/LICENSE b/packages/mcp/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/mcp/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/mcp/README.md b/packages/mcp/README.md new file mode 100644 index 0000000..75eae3d --- /dev/null +++ b/packages/mcp/README.md @@ -0,0 +1,36 @@ +# @sentinel/mcp + +`sentinel-mcp`: a stdio [Model Context Protocol](https://modelcontextprotocol.io/) +server exposing Sentinel's pre-install audit tools to agent hosts. It is a +thin client to a running Sentinel proxy — it audits nothing itself, and the +only write tool *requests* approval; it can never grant one. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install -g @sentinel/mcp@alpha +``` + +MCP client configuration: + +```json +{ + "mcpServers": { + "sentinel": { + "command": "sentinel-mcp", + "env": { "SENTINEL_PROXY": "http://localhost:4873" } + } + } +} +``` + +Tools: `sentinel_audit`, `sentinel_audit_tree`, `sentinel_capabilities`, +`sentinel_check_provenance`, `sentinel_list_violations`, `sentinel_explain`, +and `sentinel_request_approval` (request-only, never a grant). See the +[Sentinel repository](https://github.com/git-agentic/pkg-registry) for the +full documentation. + +## License + +Apache-2.0 diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 1b07eb4..f57a050 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,15 +1,52 @@ { "name": "@sentinel/mcp", - "version": "0.1.0", - "description": "Sentinel MCP server: agent-native pre-install audit tools backed by the proxy.", + "version": "0.1.0-alpha.1", + "description": "Sentinel MCP server: agent-native pre-install audit tools backed by the Sentinel proxy (stdio Model Context Protocol server).", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/mcp" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", - "bin": { "sentinel-mcp": "./dist/index.js" }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "bin": { + "sentinel-mcp": "./dist/index.js" + }, + "files": [ + "dist", + "!dist/**/*.map" + ], + "keywords": [ + "security", + "supply-chain", + "mcp", + "model-context-protocol", + "ai-agents", + "npm-audit" + ], "dependencies": { - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^3.23.8" }, - "devDependencies": { "@types/node": "^24.13.2" } + "devDependencies": { + "@types/node": "^24.13.2" + } } diff --git a/packages/mcp/src/index.ts b/packages/mcp/src/index.ts index b2d888c..e3c0e7a 100644 --- a/packages/mcp/src/index.ts +++ b/packages/mcp/src/index.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { ProxyClient, ProxyError } from "./client.js"; @@ -5,7 +6,7 @@ import { TOOLS } from "./tools.js"; /** Build an McpServer with every Sentinel tool registered against `client`. */ export function createMcpServer(client: ProxyClient): McpServer { - const server = new McpServer({ name: "sentinel", version: "0.1.0" }); + const server = new McpServer({ name: "sentinel", version: "0.1.0-alpha.1" }); for (const tool of TOOLS) { server.registerTool( tool.name, diff --git a/packages/proxy/LICENSE b/packages/proxy/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/proxy/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/proxy/README.md b/packages/proxy/README.md new file mode 100644 index 0000000..578311b --- /dev/null +++ b/packages/proxy/README.md @@ -0,0 +1,31 @@ +# @sentinel/proxy + +The Sentinel registry proxy: an Express server that transparently serves npm +packages while intercepting and auditing every tarball before install-time +code can run — plus an authoritative native publish path (`npm publish` +against Sentinel), verified namespace claims, time-locked retraction, and the +npm compatibility surface (packuments, dist-tags, unpublish-as-retraction). + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install -g @sentinel/proxy@alpha +sentinel-proxy # starts the proxy on :4873 +``` + +Point any npm/pnpm/yarn/bun client at it: + +```bash +npm install --registry http://localhost:4873 +``` + +Bins: `sentinel-proxy` (the server) and `sentinel-registry` +(`import`/`export` migration utility). Configuration is via `SENTINEL_*` +environment variables — see the +[Sentinel repository](https://github.com/git-agentic/pkg-registry) for the +full reference, architecture, and threat model. + +## License + +Apache-2.0 diff --git a/packages/proxy/package.json b/packages/proxy/package.json index 02d3a2e..dc13752 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -1,13 +1,50 @@ { "name": "@sentinel/proxy", - "version": "0.1.0", - "description": "Sentinel registry proxy: transparently serves npm packages while intercepting and auditing each tarball.", + "version": "0.1.0-alpha.1", + "description": "Sentinel registry proxy: transparently serves npm packages while intercepting and auditing each tarball, with an authoritative native publish path, verified claims, and time-locked retraction.", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/proxy" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", - "bin": { "sentinel-proxy": "./dist/index.js", "sentinel-registry": "./dist/registry-cli.js" }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "bin": { + "sentinel-proxy": "./dist/index.js", + "sentinel-registry": "./dist/registry-cli.js" + }, + "files": [ + "dist", + "!dist/**/*.map", + "public" + ], + "keywords": [ + "security", + "supply-chain", + "npm-registry", + "registry-proxy", + "npm-audit", + "package-retraction" + ], "dependencies": { - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" diff --git a/packages/sandbox/LICENSE b/packages/sandbox/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/sandbox/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/sandbox/README.md b/packages/sandbox/README.md new file mode 100644 index 0000000..3eff264 --- /dev/null +++ b/packages/sandbox/README.md @@ -0,0 +1,43 @@ +# @sentinel/sandbox + +The Sentinel capability sandbox: turns an approved capability set into +enforced install-time least-privilege. `createSandbox()` selects **Seatbelt** +on macOS and **bubblewrap** on Linux — deny-by-default writes and `$HOME` +reads, scrubbed environment, all-or-nothing network, and exec containment — +with a fail-closed contract on any other platform. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install @sentinel/sandbox@alpha +``` + +## Platform behavior in this alpha + +- **macOS (Seatbelt):** full enforcement, including the exec floor and the + sensitive-executable carve-out. No native compilation involved. +- **Linux (bubblewrap):** filesystem/network/env containment and the + exfil-tool exec carve-out are always enforced. The **exec floor** is + enforced via a Landlock helper that this package ships **as source only** + (`native/landlock-exec.c`) — no prebuilt binary, and deliberately **no + install-time compilation** (Sentinel does not run lifecycle scripts, by + posture). Without the compiled helper the exec floor is **advisory**, and + the sandbox prints a one-time notice saying so. + +To opt in to Landlock exec-floor enforcement on Linux, compile the helper +explicitly (requires `cc`): + +```bash +node node_modules/@sentinel/sandbox/scripts/build-native.mjs +``` + +The helper is verified with an ABI probe before use; any failure falls back +to the advisory floor — containment of filesystem, network, and environment +is unaffected either way. See the +[Sentinel repository](https://github.com/git-agentic/pkg-registry) for the +full documentation and threat model. + +## License + +Apache-2.0 diff --git a/packages/sandbox/package.json b/packages/sandbox/package.json index c5c2691..df73b9f 100644 --- a/packages/sandbox/package.json +++ b/packages/sandbox/package.json @@ -1,12 +1,51 @@ { "name": "@sentinel/sandbox", - "version": "0.1.0", - "description": "Sentinel sandbox: generate an OS sandbox profile from approved capabilities and run lifecycle scripts under it (macOS Seatbelt).", + "version": "0.1.0-alpha.1", + "description": "Sentinel capability sandbox: generate an OS sandbox profile from approved capabilities and run lifecycle scripts under it (macOS Seatbelt / Linux bubblewrap, deny-by-default).", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/sandbox" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", "types": "./dist/index.d.ts", - "exports": { ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" } }, - "dependencies": { "@sentinel/core": "0.1.0" }, - "devDependencies": { "@types/node": "^24.13.2" } + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "files": [ + "dist", + "!dist/**/*.map", + "!dist/landlock-exec", + "native", + "scripts/build-native.mjs" + ], + "keywords": [ + "security", + "sandbox", + "seatbelt", + "bubblewrap", + "landlock", + "install-scripts", + "least-privilege" + ], + "dependencies": { + "@sentinel/core": "0.1.0-alpha.1" + }, + "devDependencies": { + "@types/node": "^24.13.2" + } } diff --git a/packages/sandbox/test/bubblewrap.test.ts b/packages/sandbox/test/bubblewrap.test.ts index 07bd05f..f14ef70 100644 --- a/packages/sandbox/test/bubblewrap.test.ts +++ b/packages/sandbox/test/bubblewrap.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import net from "node:net"; import { spawnSync } from "node:child_process"; -import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, realpathSync } from "node:fs"; +import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, readdirSync, existsSync, realpathSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -302,4 +302,43 @@ describe("BubblewrapSandbox enforcement", { skip }, () => { // signature, so NO violation classification is asserted (the accepted // Seatbelt/bwrap telemetry asymmetry, ADR-0038/ADR-0023). }); + + test("missing Landlock helper: scripts still run on the advisory floor with a one-time notice (packaged-artifact state)", () => { + // The published @sentinel/sandbox tarball deliberately ships NO compiled + // landlock-exec (source-only, no lifecycle-script compile). Reproduce that + // state hermetically: copy the built dist/ WITHOUT the helper binary and + // drive bubblewrap.js from the copy — its helper lookup (same-dir sibling) + // then finds nothing, exactly like a fresh `npm install`. + const pkgRoot = fileURLToPath(new URL("..", import.meta.url)); + const builtDist = join(pkgRoot, "dist"); + assert.ok(existsSync(join(builtDist, "bubblewrap.js")), "run `npm run build` first — this test drives the compiled dist/"); + const tmpRoot = mkdtempSync(join(pkgRoot, ".nohelper-")); + const distCopy = join(tmpRoot, "dist"); + mkdirSync(distCopy); + try { + for (const f of readdirSync(builtDist)) { + if (f === "landlock-exec") continue; // the shipped tarball never contains the binary + if (!f.endsWith(".js")) continue; + writeFileSync(join(distCopy, f), readFileSync(join(builtDist, f))); + } + const work = realpathSync(mkdtempSync(join(tmpdir(), "bw-nohelper-"))); + const script = [ + `import { BubblewrapSandbox } from ${JSON.stringify(join(distCopy, "bubblewrap.js"))};`, + `const r = new BubblewrapSandbox().run("echo NOHELPER-OK", { cwd: process.cwd(), approved: [], homeDir: process.env.HOME });`, + `const r2 = new BubblewrapSandbox().run("echo SECOND-OK", { cwd: process.cwd(), approved: [], homeDir: process.env.HOME });`, + `process.stdout.write(JSON.stringify({ code: r.exitCode, out: r.stdout, code2: r2.exitCode, out2: r2.stdout }));`, + ].join("\n"); + const child = spawnSync(process.execPath, ["--input-type=module", "-e", script], { cwd: work, encoding: "utf8" }); + assert.equal(child.status, 0, child.stderr); + const res = JSON.parse(child.stdout) as { code: number; out: string; code2: number; out2: string }; + assert.equal(res.code, 0, "script must still run on the advisory floor"); + assert.match(res.out, /NOHELPER-OK/); + assert.equal(res.code2, 0); + assert.match(res.out2, /SECOND-OK/); + const notices = child.stderr.match(/Landlock exec floor unavailable/g) ?? []; + assert.equal(notices.length, 1, `advisory notice must print exactly once per process, got ${notices.length}:\n${child.stderr}`); + } finally { + rmSync(tmpRoot, { recursive: true, force: true }); + } + }); }); diff --git a/packages/steward/LICENSE b/packages/steward/LICENSE new file mode 100644 index 0000000..a222e86 --- /dev/null +++ b/packages/steward/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 git-agentic + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/steward/README.md b/packages/steward/README.md new file mode 100644 index 0000000..aba695b --- /dev/null +++ b/packages/steward/README.md @@ -0,0 +1,31 @@ +# @sentinel/steward + +`sentinel-steward`: the Sentinel namespace-claim steward — an authenticated +operational service for exact-apex DNS TXT claim challenges, three-tier +grandfathering, claimant-key-signed transfers, 12-month renewal and freeze +lifecycle, 30-day timelocked changes, and atomic Ed25519-signed claim- and +retraction-corpus releases that Sentinel proxies consume offline. + +> **Alpha.** This is a pre-1.0 preview (`0.1.0-alpha.1`). APIs may change +> without notice. Not production-ready. + +```bash +npm install -g @sentinel/steward@alpha +``` + +All four variables are required: + +```bash +SENTINEL_STEWARD_TOKEN=operator-secret \ +SENTINEL_STEWARD_STATE=./steward/state.json \ +SENTINEL_CLAIM_CORPUS_PRIVATE_KEY=./steward/private.pem \ +SENTINEL_CLAIM_CORPUS_RELEASE_DIR=./steward/release \ +sentinel-steward +``` + +See the [Sentinel repository](https://github.com/git-agentic/pkg-registry) +for the claim lifecycle, corpus format, and threat model. + +## License + +Apache-2.0 diff --git a/packages/steward/package.json b/packages/steward/package.json index 517d6ef..0234a0f 100644 --- a/packages/steward/package.json +++ b/packages/steward/package.json @@ -1,13 +1,48 @@ { "name": "@sentinel/steward", - "version": "0.1.0", - "description": "Sentinel namespace-claim steward and signed corpus issuer.", + "version": "0.1.0-alpha.1", + "description": "Sentinel namespace-claim steward: DNS TXT claim verification, renewal/freeze lifecycle, timelocked transfers, and Ed25519-signed claim/retraction corpus releases.", "license": "Apache-2.0", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/git-agentic/pkg-registry.git", + "directory": "packages/steward" + }, + "homepage": "https://github.com/git-agentic/pkg-registry#readme", + "bugs": "https://github.com/git-agentic/pkg-registry/issues", + "engines": { + "node": ">=22" + }, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, "main": "./dist/index.js", - "bin": { "sentinel-steward": "./dist/index.js" }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "bin": { + "sentinel-steward": "./dist/index.js" + }, + "files": [ + "dist", + "!dist/**/*.map" + ], + "keywords": [ + "security", + "supply-chain", + "namespace-claims", + "dns-verification", + "ed25519", + "npm-registry" + ], "dependencies": { - "@sentinel/core": "0.1.0", + "@sentinel/core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts new file mode 100644 index 0000000..d57fd4f --- /dev/null +++ b/scripts/release-smoke.ts @@ -0,0 +1,274 @@ +// Release smoke test: pack every publishable workspace, install the packed +// tarballs into a FRESH temp project (no monorepo/workspace resolution), and +// verify the artifacts actually work: +// - every package imports +// - type declarations resolve under NodeNext +// - every declared bin starts (--help/--version where supported; controlled +// startup/config-validation otherwise) +// - the proxy boots, serves the dashboard, and shuts down cleanly +// - the MCP server answers an initialize handshake +// - the steward fail-closes on missing config and boots with full config +// - internal @sentinel/* dependencies resolve from the packed tarballs only +// +// Requires network access (third-party deps install from the public registry). +// Usage: npx tsx scripts/release-smoke.ts [--json ] [--pack-dest

] +// --pack-dest keeps the packed tarballs in (the release workflow +// uploads exactly the artifacts this script validated). +import { execFileSync, spawn, type ChildProcess } from "node:child_process"; +import { createHash, generateKeyPairSync } from "node:crypto"; +import { mkdtempSync, writeFileSync, readFileSync, mkdirSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const WORKSPACES = ["core", "proxy", "sandbox", "cli", "mcp", "action", "steward"] as const; +const VERSION = "0.1.0-alpha.1"; + +interface TarballInfo { name: string; file: string; bytes: number; sha256: string; files: number; unpacked: number } +const results: { tarballs: TarballInfo[]; checks: { name: string; ok: boolean; detail: string }[] } = { tarballs: [], checks: [] }; + +function check(name: string, fn: () => string): void { + try { + const detail = fn(); + results.checks.push({ name, ok: true, detail }); + console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`); + } catch (e) { + results.checks.push({ name, ok: false, detail: (e as Error).message }); + console.error(` ✗ ${name} — ${(e as Error).message}`); + } +} + +async function checkAsync(name: string, fn: () => Promise): Promise { + try { + const detail = await fn(); + results.checks.push({ name, ok: true, detail }); + console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`); + } catch (e) { + results.checks.push({ name, ok: false, detail: (e as Error).message }); + console.error(` ✗ ${name} — ${(e as Error).message}`); + } +} + +function run(cmd: string, args: string[], opts: { cwd: string; env?: NodeJS.ProcessEnv } = { cwd: repoRoot }): string { + return execFileSync(cmd, args, { cwd: opts.cwd, encoding: "utf8", env: opts.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] }); +} + +/** Run expecting a non-zero exit; returns { code, output }. Throws if it exits 0. */ +function runExpectFail(cmd: string, args: string[], opts: { cwd: string; env?: NodeJS.ProcessEnv }): { code: number; output: string } { + try { + execFileSync(cmd, args, { cwd: opts.cwd, encoding: "utf8", env: opts.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] }); + } catch (e) { + const err = e as { status?: number; stdout?: string; stderr?: string }; + return { code: err.status ?? -1, output: `${err.stdout ?? ""}${err.stderr ?? ""}` }; + } + throw new Error("expected non-zero exit, got 0"); +} + +/** Spawn a long-running process, wait for a stdout/stderr marker, run probe, then kill. */ +async function withServer( + file: string, args: string[], env: NodeJS.ProcessEnv, cwd: string, marker: RegExp, timeoutMs: number, + probe: (child: ChildProcess, output: () => string) => Promise, +): Promise { + const child = spawn(file, args, { cwd, env, stdio: ["pipe", "pipe", "pipe"] }); + let out = ""; + child.stdout!.on("data", (d: Buffer) => { out += d.toString(); }); + child.stderr!.on("data", (d: Buffer) => { out += d.toString(); }); + try { + await new Promise((resolvePromise, reject) => { + const t = setTimeout(() => reject(new Error(`timeout waiting for ${marker} — output:\n${out.slice(0, 2000)}`)), timeoutMs); + const iv = setInterval(() => { + if (marker.test(out)) { clearTimeout(t); clearInterval(iv); resolvePromise(); } + if (child.exitCode !== null) { clearTimeout(t); clearInterval(iv); reject(new Error(`exited ${child.exitCode} before ${marker} — output:\n${out.slice(0, 2000)}`)); } + }, 50); + }); + return await probe(child, () => out); + } finally { + child.kill("SIGTERM"); + await new Promise((r) => setTimeout(r, 300)); + if (child.exitCode === null) child.kill("SIGKILL"); + } +} + +// --------------------------------------------------------------------------- +// 1. Pack every workspace +// --------------------------------------------------------------------------- +const destIdx = process.argv.indexOf("--pack-dest"); +const packDir = destIdx !== -1 && process.argv[destIdx + 1] + ? (mkdirSync(resolve(process.argv[destIdx + 1]!), { recursive: true }), resolve(process.argv[destIdx + 1]!)) + : mkdtempSync(join(tmpdir(), "sentinel-pack-")); +console.log(`\n[1/5] packing ${WORKSPACES.length} workspaces → ${packDir}`); +for (const ws of WORKSPACES) { + const json = run("npm", ["pack", "--json", "--pack-destination", packDir], { cwd: join(repoRoot, "packages", ws) }); + const info = (JSON.parse(json) as { filename: string; size: number; entryCount: number; unpackedSize: number }[])[0]; + const file = join(packDir, info.filename); + const sha256 = createHash("sha256").update(readFileSync(file)).digest("hex"); + results.tarballs.push({ name: `@sentinel/${ws}`, file: info.filename, bytes: info.size, sha256, files: info.entryCount, unpacked: info.unpackedSize }); + console.log(` ${info.filename} ${info.size} B ${info.entryCount} files sha256:${sha256.slice(0, 16)}…`); +} + +// --------------------------------------------------------------------------- +// 2. Fresh project: install ONLY the packed tarballs (+ registry for 3rd-party) +// --------------------------------------------------------------------------- +const proj = mkdtempSync(join(tmpdir(), "sentinel-smoke-")); +console.log(`\n[2/5] fresh install into ${proj}`); +const fileDep = (ws: string) => `file:${join(packDir, results.tarballs.find((t) => t.name === `@sentinel/${ws}`)!.file)}`; +const pkgJson = { + name: "sentinel-release-smoke", private: true, version: "0.0.0", type: "module", + dependencies: Object.fromEntries(WORKSPACES.map((ws) => [`@sentinel/${ws}`, fileDep(ws)])), + // Internal deps are pinned to the (unpublished) exact prerelease version, so + // transitive resolution must be forced to the local tarballs. + overrides: { "@sentinel/core": fileDep("core"), "@sentinel/proxy": fileDep("proxy"), "@sentinel/sandbox": fileDep("sandbox") }, +}; +writeFileSync(join(proj, "package.json"), JSON.stringify(pkgJson, null, 2)); +run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], { cwd: proj }); +console.log(" installed"); +check("internal deps resolved from tarballs (not registry)", () => { + const lock = JSON.parse(readFileSync(join(proj, "package-lock.json"), "utf8")) as { packages: Record }; + const bad = Object.entries(lock.packages).filter(([k, v]) => k.includes("@sentinel/") && v.resolved && !v.resolved.startsWith("file:")); + if (bad.length) throw new Error(`registry-resolved: ${bad.map(([k]) => k).join(", ")}`); + return "all @sentinel/* resolved file:"; +}); + +// --------------------------------------------------------------------------- +// 3. Imports + type declarations +// --------------------------------------------------------------------------- +console.log(`\n[3/5] imports + types`); +for (const ws of WORKSPACES) { + check(`import @sentinel/${ws}`, () => { + run(process.execPath, ["-e", `import("@sentinel/${ws}").then((m)=>{ if(!m || typeof m !== "object") throw new Error("empty module") })`], { cwd: proj }); + return ""; + }); +} +check("ENGINE_VERSION matches release", () => { + const v = run(process.execPath, ["-e", `import("@sentinel/core").then((m)=>console.log(m.ENGINE_VERSION))`], { cwd: proj }).trim(); + if (v !== VERSION) throw new Error(`ENGINE_VERSION=${v}, expected ${VERSION}`); + return v; +}); +check("type declarations resolve (tsc --noEmit, NodeNext)", () => { + run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error", "-D", "typescript@^6"], { cwd: proj }); + writeFileSync(join(proj, "typecheck.ts"), [ + `import { runAudit, score, DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@sentinel/core";`, + `import { createServer, NpmUpstream, type Upstream } from "@sentinel/proxy";`, + `import { createSandbox, scrubEnv } from "@sentinel/sandbox";`, + `const p: EnterprisePolicy = DEFAULT_POLICY;`, + `void p; void runAudit; void score; void createServer; void createSandbox; void scrubEnv;`, + `const u: Upstream | null = null; void u;`, + `const r: AuditReport | null = null; void r; void NpmUpstream;`, + ].join("\n")); + writeFileSync(join(proj, "tsconfig.json"), JSON.stringify({ + compilerOptions: { module: "NodeNext", moduleResolution: "NodeNext", target: "ES2023", strict: true, noEmit: true, skipLibCheck: true, types: [] }, + files: ["typecheck.ts"], + })); + run(join(proj, "node_modules", ".bin", "tsc"), ["-p", proj], { cwd: proj }); + return ""; +}); + +// --------------------------------------------------------------------------- +// 4. Binaries +// --------------------------------------------------------------------------- +console.log(`\n[4/5] binaries`); +const bin = (name: string) => join(proj, "node_modules", ".bin", name); + +check("sentinel --version", () => { + const v = run(bin("sentinel"), ["--version"], { cwd: proj }).trim(); + if (v !== VERSION) throw new Error(`got ${v}, expected ${VERSION}`); + return v; +}); +check("sentinel --help prints usage", () => { + const out = run(bin("sentinel"), ["--help"], { cwd: proj }); + if (!/Usage:/i.test(out)) throw new Error(`no usage text:\n${out.slice(0, 300)}`); + return ""; +}); +check("sentinel-registry --help prints usage", () => { + const out = run(bin("sentinel-registry"), ["--help"], { cwd: proj }); + if (!/Usage:/i.test(out)) throw new Error(`no usage text:\n${out.slice(0, 300)}`); + return ""; +}); +check("sentinel-script-shell starts (controlled failure, no module errors)", () => { + const { output } = runExpectFail(bin("sentinel-script-shell"), [], { cwd: proj }); + if (/ERR_MODULE_NOT_FOUND|Cannot find (module|package)/.test(output)) throw new Error(`module resolution failure:\n${output.slice(0, 800)}`); + return "controlled non-zero exit"; +}); +check("sentinel-ci starts (controlled failure without lockfile, no module errors)", () => { + const empty = mkdtempSync(join(tmpdir(), "sentinel-ci-empty-")); + try { + const { output } = runExpectFail(bin("sentinel-ci"), [], { cwd: empty, env: { ...process.env, GITHUB_OUTPUT: "", GITHUB_STEP_SUMMARY: "" } }); + if (/ERR_MODULE_NOT_FOUND|Cannot find (module|package)/.test(output)) throw new Error(`module resolution failure:\n${output.slice(0, 800)}`); + return "controlled non-zero exit"; + } finally { rmSync(empty, { recursive: true, force: true }); } +}); +check("sentinel-steward fail-closed on missing config", () => { + const { code, output } = runExpectFail(bin("sentinel-steward"), [], { cwd: proj, env: { PATH: process.env.PATH! } }); + if (code !== 1 || !/FATAL/.test(output)) throw new Error(`expected exit 1 + FATAL, got ${code}: ${output.slice(0, 300)}`); + return "exit 1 + FATAL"; +}); + +const proxyPort = 40000 + Math.floor(Math.random() * 20000); +await checkAsync("sentinel-proxy boots, serves dashboard, exits cleanly", async () => { + return withServer(bin("sentinel-proxy"), [], { ...process.env, SENTINEL_PORT: String(proxyPort) }, proj, /listening on/, 20000, async () => { + const res = await fetch(`http://localhost:${proxyPort}/`); + if (res.status !== 200) throw new Error(`GET / → ${res.status}`); + const body = await res.text(); + if (!/sentinel/i.test(body)) throw new Error("dashboard body missing 'sentinel'"); + return `GET / → 200 (${body.length} B)`; + }); +}); + +await checkAsync("sentinel-mcp answers initialize", async () => { + const child = spawn(bin("sentinel-mcp"), [], { cwd: proj, env: process.env, stdio: ["pipe", "pipe", "pipe"] }); + let out = ""; + child.stdout!.on("data", (d: Buffer) => { out += d.toString(); }); + try { + child.stdin!.write(JSON.stringify({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "smoke", version: "0.0.0" } } }) + "\n"); + await new Promise((resolvePromise, reject) => { + const t = setTimeout(() => reject(new Error(`no initialize response — output: ${out.slice(0, 500)}`)), 10000); + const iv = setInterval(() => { + if (out.includes('"serverInfo"') || out.includes('"result"')) { clearTimeout(t); clearInterval(iv); resolvePromise(); } + if (child.exitCode !== null) { clearTimeout(t); clearInterval(iv); reject(new Error(`exited ${child.exitCode}: ${out.slice(0, 500)}`)); } + }, 50); + }); + return "initialize → result"; + } finally { + child.kill("SIGTERM"); + await new Promise((r) => setTimeout(r, 200)); + if (child.exitCode === null) child.kill("SIGKILL"); + } +}); + +await checkAsync("sentinel-steward boots with full config", async () => { + const stewardDir = mkdtempSync(join(tmpdir(), "sentinel-steward-")); + const { privateKey } = generateKeyPairSync("ed25519"); + const keyPath = join(stewardDir, "key.pem"); + writeFileSync(keyPath, privateKey.export({ type: "pkcs8", format: "pem" })); + mkdirSync(join(stewardDir, "release"), { recursive: true }); + const port = proxyPort + 1; + const env = { + ...process.env, + SENTINEL_STEWARD_TOKEN: "smoke-token", + SENTINEL_STEWARD_STATE: join(stewardDir, "state.json"), + SENTINEL_CLAIM_CORPUS_PRIVATE_KEY: keyPath, + SENTINEL_CLAIM_CORPUS_RELEASE_DIR: join(stewardDir, "release"), + SENTINEL_STEWARD_PORT: String(port), + }; + try { + return await withServer(bin("sentinel-steward"), [], env, proj, /steward listening/, 15000, async () => "listening"); + } finally { rmSync(stewardDir, { recursive: true, force: true }); } +}); + +// --------------------------------------------------------------------------- +// 5. Summary +// --------------------------------------------------------------------------- +console.log(`\n[5/5] summary`); +const failed = results.checks.filter((c) => !c.ok); +console.log(` tarballs: ${results.tarballs.length}; checks: ${results.checks.length - failed.length}/${results.checks.length} passed`); +const jsonIdx = process.argv.indexOf("--json"); +if (jsonIdx !== -1 && process.argv[jsonIdx + 1]) { + writeFileSync(process.argv[jsonIdx + 1]!, JSON.stringify(results, null, 2)); + console.log(` wrote ${process.argv[jsonIdx + 1]}`); +} +if (failed.length > 0) { + console.error(`\nFAILED checks:\n${failed.map((f) => ` - ${f.name}: ${f.detail}`).join("\n")}`); + process.exit(1); +} +console.log("\nrelease smoke: ALL PASS"); diff --git a/sentinel-threat-model.md b/sentinel-threat-model.md index 511d8ba..92fab80 100644 --- a/sentinel-threat-model.md +++ b/sentinel-threat-model.md @@ -291,6 +291,14 @@ and stays filesystem+network confined as before. The Phase 29 `/dev/null` carve-out is unchanged (Landlock is allow-list-only and can't deny a literal under an allowed dir). `native` is advisory-only on both platforms by decision. A spawned child inherits the filesystem/network confinement on both platforms. +**Distribution note (ADR-0052):** the published `@sentinel/sandbox` npm package +ships the Landlock helper as *source only* — no prebuilt binary (it would be +architecture-specific presented as portable) and no install-time compilation +(a posture violation for a tool that guards against lifecycle scripts). A +fresh npm install therefore runs the advisory exec floor on Linux, announced +by a one-time notice, until the operator explicitly compiles the helper +(`node node_modules/@sentinel/sandbox/scripts/build-native.mjs`); monorepo +builds are unchanged. A cross-platform exec floor now exists (macOS Seatbelt, Linux Landlock where available); [issue #8](https://github.com/git-agentic/pkg-registry/issues/8) is closed, with the Landlock-availability caveat documented here. @@ -318,7 +326,10 @@ Stated plainly. Each is a deliberate, recorded trade-off, not an oversight. floor on hosts where Landlock + a compiled `cc` toolchain are available (fail-open, pre-checked detection with a one-time notice on fallback) — a host without either stays on the Phase 29 advisory floor, filesystem+network - confined as before, no availability regression. `native` loading is not + confined as before, no availability regression. npm-installed builds start + in exactly this advisory state — the published package ships helper source, + not a binary, and enforcing the Linux floor requires an explicit operator + compile (ADR-0052). `native` loading is not distinguishable from reading at the path level and stays a scoring signal. A cross-platform floor now exists; see §3.9; [issue #8](https://github.com/git-agentic/pkg-registry/issues/8) is closed From a25e3a0012139720ba2f87d134a571169cce9b82 Mon Sep 17 00:00:00 2001 From: Toni Bergholm Date: Tue, 14 Jul 2026 07:31:14 +0300 Subject: [PATCH 2/3] =?UTF-8?q?Rename=20npm=20scope:=20@sentinel=20?= =?UTF-8?q?=E2=86=92=20@agentic-sentinel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sentinel npm scope/name family is taken (unscoped `sentinel`, `@sentinel-password/*`, etc.), so the release publishes under @agentic-sentinel. Mechanical rename across manifests, imports, tests, scripts, workflow, and current docs; historical records (docs/archive/, ADRs 0001-0051) keep the old spelling verbatim. Bin names (sentinel, sentinel-proxy, sentinel-mcp, ...) are unchanged. Lockfile regenerated; full suite green (997/994/3 skipped) and pack-smoke 19/19 under the new names. Claude-Session: https://claude.ai/code/session_01LjqCaCwPby6EGi4RmBVtEW --- .github/workflows/release.yml | 32 +++---- ARCHITECTURE.md | 30 +++---- CLAUDE.md | 18 ++-- README.md | 14 +-- SECURITY.md | 2 +- .../0052-native-helper-release-packaging.md | 8 +- docs/adr/README.md | 2 +- docs/product/registry-roadmap.md | 2 +- docs/release-process.md | 16 ++-- docs/releases/v0.1.0-alpha.1.md | 30 +++---- ...6-07-12-native-payload-loader-detection.md | 12 +-- ...-native-payload-loader-detection-design.md | 2 +- package-lock.json | 86 +++++++++---------- packages/action/README.md | 4 +- packages/action/package.json | 6 +- packages/action/src/index.ts | 6 +- packages/action/src/report.ts | 4 +- packages/action/src/run.ts | 4 +- packages/action/test/report.test.ts | 2 +- packages/action/test/run-e2e.test.ts | 2 +- packages/cli/README.md | 8 +- packages/cli/package.json | 6 +- packages/cli/src/enforce.ts | 2 +- packages/cli/src/format.ts | 2 +- packages/cli/src/index.ts | 4 +- packages/cli/src/script-shell.ts | 6 +- packages/cli/test/attest-cli-e2e.test.ts | 2 +- packages/cli/test/audit-tree-cli-e2e.test.ts | 2 +- packages/cli/test/explain-cli-e2e.test.ts | 2 +- packages/cli/test/format-tree.test.ts | 2 +- .../cli/test/policy-authoring-cli-e2e.test.ts | 4 +- packages/cli/test/policy.test.ts | 2 +- packages/cli/test/run-scripts.test.ts | 2 +- .../cli/test/stats-history-cli-e2e.test.ts | 4 +- packages/core/README.md | 6 +- packages/core/package.json | 2 +- packages/core/src/index.ts | 2 +- packages/core/test/package-contents.test.ts | 6 +- packages/mcp/README.md | 4 +- packages/mcp/package.json | 4 +- packages/mcp/src/client.ts | 2 +- packages/mcp/src/format.ts | 2 +- packages/mcp/src/tools.ts | 2 +- packages/mcp/test/client-auth.test.ts | 2 +- packages/mcp/test/client.test.ts | 2 +- packages/mcp/test/server-e2e.test.ts | 2 +- packages/mcp/test/tools.test.ts | 2 +- packages/proxy/README.md | 4 +- packages/proxy/package.json | 4 +- packages/proxy/src/approval-requests.ts | 2 +- packages/proxy/src/approvals.ts | 2 +- packages/proxy/src/authz.ts | 2 +- packages/proxy/src/cooldown.ts | 2 +- packages/proxy/src/history-db.ts | 2 +- packages/proxy/src/index.ts | 2 +- packages/proxy/src/private-store.ts | 4 +- packages/proxy/src/reconcile.ts | 2 +- packages/proxy/src/registry-mode.ts | 2 +- packages/proxy/src/resolution.ts | 6 +- packages/proxy/src/server.ts | 2 +- packages/proxy/src/store.ts | 2 +- packages/proxy/src/upstream.ts | 2 +- .../proxy/test/approval-requests-e2e.test.ts | 2 +- packages/proxy/test/audit-tree-e2e.test.ts | 2 +- .../test/audit-tree-integrity-e2e.test.ts | 2 +- .../proxy/test/audit-tree-limits-e2e.test.ts | 2 +- packages/proxy/test/auth-config.test.ts | 2 +- packages/proxy/test/authz-e2e.test.ts | 2 +- packages/proxy/test/authz-unit.test.ts | 2 +- .../proxy/test/claim-corpus-startup.test.ts | 2 +- .../proxy/test/claim-lifecycle-e2e.test.ts | 2 +- packages/proxy/test/coalesce-e2e.test.ts | 2 +- packages/proxy/test/compatibility-e2e.test.ts | 2 +- packages/proxy/test/cooldown-e2e.test.ts | 2 +- packages/proxy/test/cooldown.test.ts | 2 +- packages/proxy/test/enforce-e2e.test.ts | 2 +- packages/proxy/test/explain-e2e.test.ts | 2 +- .../proxy/test/history-db-queries.test.ts | 2 +- packages/proxy/test/history-db.test.ts | 2 +- .../proxy/test/history-endpoints-e2e.test.ts | 4 +- .../proxy/test/history-writethrough.test.ts | 2 +- .../proxy/test/known-advisory-e2e.test.ts | 2 +- .../test/known-vulnerability-e2e.test.ts | 2 +- .../proxy/test/payload-loader-e2e.test.ts | 2 +- .../proxy/test/policy-preview-e2e.test.ts | 4 +- packages/proxy/test/policy-startup.test.ts | 2 +- packages/proxy/test/private-serve.test.ts | 2 +- packages/proxy/test/private-store.test.ts | 2 +- packages/proxy/test/provenance-verify.test.ts | 2 +- packages/proxy/test/proxy.test.ts | 2 +- .../proxy/test/public-base-url-e2e.test.ts | 2 +- packages/proxy/test/publish.test.ts | 2 +- packages/proxy/test/rate-limit-e2e.test.ts | 2 +- packages/proxy/test/reconcile.test.ts | 2 +- .../proxy/test/registry-migration.test.ts | 2 +- .../proxy/test/registry-mode-startup.test.ts | 2 +- .../proxy/test/release-anomaly-e2e.test.ts | 2 +- packages/proxy/test/resolution.test.ts | 2 +- packages/proxy/test/retraction-e2e.test.ts | 2 +- packages/proxy/test/signature-verify.test.ts | 2 +- packages/proxy/test/tree.test.ts | 2 +- packages/proxy/test/typosquat-e2e.test.ts | 2 +- .../proxy/test/violation-enforce-e2e.test.ts | 2 +- packages/proxy/test/violations-e2e.test.ts | 2 +- .../proxy/test/violations-startup.test.ts | 2 +- packages/sandbox/README.md | 6 +- packages/sandbox/package.json | 4 +- packages/sandbox/src/bubblewrap.ts | 2 +- packages/sandbox/src/bwrap.ts | 2 +- packages/sandbox/src/deny-set.ts | 2 +- packages/sandbox/src/env.ts | 2 +- packages/sandbox/src/profile.ts | 2 +- packages/sandbox/src/runner.ts | 2 +- packages/sandbox/src/seatbelt.ts | 2 +- packages/sandbox/src/types.ts | 2 +- packages/sandbox/test/bubblewrap.test.ts | 4 +- packages/sandbox/test/bwrap.test.ts | 2 +- packages/sandbox/test/deny-set.test.ts | 2 +- packages/sandbox/test/env.test.ts | 2 +- packages/sandbox/test/profile.test.ts | 2 +- packages/sandbox/test/runner.test.ts | 2 +- packages/sandbox/test/seatbelt.test.ts | 2 +- packages/steward/README.md | 4 +- packages/steward/package.json | 4 +- packages/steward/src/server.ts | 2 +- packages/steward/src/steward.ts | 2 +- packages/steward/test/steward.test.ts | 2 +- scripts/benchmark-publish.ts | 2 +- scripts/compat-clients.ts | 2 +- scripts/demo.ts | 2 +- scripts/release-smoke.ts | 26 +++--- sentinel-threat-model.md | 4 +- 132 files changed, 295 insertions(+), 295 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e8e55af..5ee3586 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,8 +170,8 @@ jobs: set -euo pipefail VERSION="${RELEASE_TAG#v}" for p in core proxy sandbox mcp steward cli action; do - if npm view "@sentinel/$p@$VERSION" version >/dev/null 2>&1; then - echo "::error::@sentinel/$p@$VERSION already exists on the registry — refusing to continue"; exit 1 + if npm view "@agentic-sentinel/$p@$VERSION" version >/dev/null 2>&1; then + echo "::error::@agentic-sentinel/$p@$VERSION already exists on the registry — refusing to continue"; exit 1 fi done echo "no target version exists — safe to publish" @@ -184,13 +184,13 @@ jobs: VERSION="${RELEASE_TAG#v}" published="" for p in core proxy sandbox mcp steward cli action; do - t="release-artifacts/sentinel-$p-$VERSION.tgz" - echo "publishing @sentinel/$p@$VERSION" + t="release-artifacts/agentic-sentinel-$p-$VERSION.tgz" + echo "publishing @agentic-sentinel/$p@$VERSION" if ! npm publish "$t" --access public --tag alpha --provenance; then - echo "::error::publish of @sentinel/$p failed. Already published (immutable): ${published:-none}. Do NOT unpublish; fix forward."; exit 1 + echo "::error::publish of @agentic-sentinel/$p failed. Already published (immutable): ${published:-none}. Do NOT unpublish; fix forward."; exit 1 fi - published="$published @sentinel/$p" - echo "- @sentinel/$p@$VERSION published" >> "$GITHUB_STEP_SUMMARY" + published="$published @agentic-sentinel/$p" + echo "- @agentic-sentinel/$p@$VERSION published" >> "$GITHUB_STEP_SUMMARY" done - name: Verify every published package via npm view run: | @@ -198,14 +198,14 @@ jobs: VERSION="${RELEASE_TAG#v}" for p in core proxy sandbox mcp steward cli action; do for i in 1 2 3 4 5; do - got="$(npm view "@sentinel/$p@$VERSION" version 2>/dev/null || true)" + got="$(npm view "@agentic-sentinel/$p@$VERSION" version 2>/dev/null || true)" [ "$got" = "$VERSION" ] && break sleep 15 done - [ "$got" = "$VERSION" ] || { echo "::error::@sentinel/$p@$VERSION not visible after publish"; exit 1; } - tag_alpha="$(npm view "@sentinel/$p" dist-tags.alpha)" - [ "$tag_alpha" = "$VERSION" ] || { echo "::error::@sentinel/$p dist-tag alpha is $tag_alpha, expected $VERSION"; exit 1; } - echo "@sentinel/$p@$VERSION visible, dist-tag alpha OK" + [ "$got" = "$VERSION" ] || { echo "::error::@agentic-sentinel/$p@$VERSION not visible after publish"; exit 1; } + tag_alpha="$(npm view "@agentic-sentinel/$p" dist-tags.alpha)" + [ "$tag_alpha" = "$VERSION" ] || { echo "::error::@agentic-sentinel/$p dist-tag alpha is $tag_alpha, expected $VERSION"; exit 1; } + echo "@agentic-sentinel/$p@$VERSION visible, dist-tag alpha OK" done - name: Install the published packages from the public registry in a clean project run: | @@ -217,13 +217,13 @@ jobs: # retry: registry propagation can lag the view endpoint for i in 1 2 3 4 5; do npm install --no-audit --no-fund \ - "@sentinel/core@$VERSION" "@sentinel/proxy@$VERSION" "@sentinel/sandbox@$VERSION" \ - "@sentinel/mcp@$VERSION" "@sentinel/steward@$VERSION" "@sentinel/cli@$VERSION" \ - "@sentinel/action@$VERSION" && break + "@agentic-sentinel/core@$VERSION" "@agentic-sentinel/proxy@$VERSION" "@agentic-sentinel/sandbox@$VERSION" \ + "@agentic-sentinel/mcp@$VERSION" "@agentic-sentinel/steward@$VERSION" "@agentic-sentinel/cli@$VERSION" \ + "@agentic-sentinel/action@$VERSION" && break sleep 20 done ./node_modules/.bin/sentinel --version | grep -qx "$VERSION" - node -e "import('@sentinel/core').then(m=>{if(m.ENGINE_VERSION!=='$VERSION')process.exit(1)})" + node -e "import('@agentic-sentinel/core').then(m=>{if(m.ENGINE_VERSION!=='$VERSION')process.exit(1)})" echo "clean-project registry install OK" - name: Create the GitHub prerelease (only after npm verification) env: diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a09b0f2..ec60851 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -61,17 +61,17 @@ package is installed and approved is out of scope. Seven packages (npm workspaces monorepo; key registry packages below): -- **`@sentinel/core`** — the audit engine. Pure, dependency-light, deterministic. +- **`@agentic-sentinel/core`** — the audit engine. Pure, dependency-light, deterministic. Tarball extraction, the rules, scoring, the data model, and the LLM adapter interface. No HTTP, no Express — so it is trivially unit-testable and reusable (CLI, proxy, CI all import it). -- **`@sentinel/proxy`** — Express server implementing the npm registry HTTP API +- **`@agentic-sentinel/proxy`** — Express server implementing the npm registry HTTP API surface we need (`GET /:pkg`, `GET /:pkg/-/:tarball`). Pluggable upstream (`NpmUpstream` for the real registry, `LocalFixtureUpstream` for hermetic tests). Owns the verdict cache + audit store and serves the dashboard. -- **`@sentinel/cli`** — `sentinel audit ` (one-shot) and `sentinel install …` +- **`@agentic-sentinel/cli`** — `sentinel audit ` (one-shot) and `sentinel install …` (sets `registry` to the proxy and runs npm, showing the pre-install verdict). -- **`@sentinel/steward`** — authenticated DNS-claim issuance, renewal/freeze, +- **`@agentic-sentinel/steward`** — authenticated DNS-claim issuance, renewal/freeze, timelocked ownership changes, and signed offline claim-corpus releases. It is operationally separate from the proxy's offline resolution path. - **dashboard** — a single self-contained HTML page served by the proxy at `/`. @@ -182,7 +182,7 @@ the policy hash. Frozen/disputed claims remain native for reads but reject write trusted-publisher enrollments require a matching offline-verified Sigstore SLSA identity. Stored native versions snapshot the claim namespace, domain, and claimant key at publication, so an ownership change cannot re-attribute history. -`@sentinel/steward` performs exact-apex DNS challenges, derives grandfather tiers +`@agentic-sentinel/steward` performs exact-apex DNS challenges, derives grandfather tiers from steward-fetched upstream evidence, verifies claimant-key transfer signatures, applies renewal/domain-change freezes, and atomically publishes versioned directories after 30-day announced changes (ADR-0046). Mandatory @@ -241,7 +241,7 @@ never stored. ### 3.6 Sandbox enforcement (Phases 3–5, ADR-0011/0016/0017/0018) -`@sentinel/sandbox` turns an *approved* capability set into *enforced* runtime +`@agentic-sentinel/sandbox` turns an *approved* capability set into *enforced* runtime least-privilege on macOS and Linux: `generateProfile(approved, {homeDir})` emits an allow-default + deny-sensitive Seatbelt (SBPL) profile, each deny relaxed by an approved capability; the `SeatbeltSandbox` runs each lifecycle script under it via `sandbox-exec` (failing closed @@ -276,7 +276,7 @@ any negative falls back to the Phase 29 advisory floor with a one-time notice, so a Landlock-less or no-`cc` host never regresses. `computeDenySet` gains a `linux-landlock` `execFloorMode` and `classifyViolation` confirms a floor-outside exec denial as `exec-floor-deny`. The *published* -`@sentinel/sandbox` package ships the helper as source only +`@agentic-sentinel/sandbox` package ships the helper as source only (`native/landlock-exec.c` + `scripts/build-native.mjs`) — never a prebuilt binary and never a `postinstall` compile; a fresh npm install runs this same advisory fallback until the operator explicitly compiles the helper @@ -358,7 +358,7 @@ by sniffing for `__metadata:`), and `pnpm-lock.yaml` (YAML across lockfile versi into the same deduped, sorted `{name, version, integrity?}` `Coordinate[]` regardless of format (skipping the root entry and `link:`/`file:` deps). Berry checksums are not SRI-shaped, so berry-parsed coordinates carry no `integrity`. The `yaml` package -(`^2.9.0`) backing the pnpm/berry parsers is a dependency of `@sentinel/core` only. The CLI +(`^2.9.0`) backing the pnpm/berry parsers is a dependency of `@agentic-sentinel/core` only. The CLI POSTs the coordinates (plus an optional `failOnError` flag) to `POST /-/audit-tree`. The proxy fans out with bounded concurrency over the same integrity-cached `auditVersion()` path used by the tarball route, then rolls the per-package verdicts into a worst-case-wins @@ -762,7 +762,7 @@ deferred. Phases 1–16 gate installs and lockfiles, but only when a human or CI job already knows to run `sentinel audit-tree` against a proxy someone started. Phase 17 adds a self-contained on-ramp into GitHub PRs: a new -**`@sentinel/action`** workspace (`packages/action`, bin `sentinel-ci`) that +**`@agentic-sentinel/action`** workspace (`packages/action`, bin `sentinel-ci`) that needs nothing already running. - **`runCi(opts)`** (`packages/action/src/run.ts`) self-boots @@ -797,9 +797,9 @@ needs nothing already running. marker instead of always appending a new one. `.github/workflows/sentinel-example.yml` shows minimal usage. - **The proxy entrypoint-guard root fix.** `packages/proxy/src/index.ts`'s - `main()` is now guarded the same way `@sentinel/mcp`'s bin already is + `main()` is now guarded the same way `@agentic-sentinel/mcp`'s bin already is (`isEntrypoint()` comparing `import.meta.url` to the resolved - `process.argv[1]`) — importing `@sentinel/proxy` for its exports no + `process.argv[1]`) — importing `@agentic-sentinel/proxy` for its exports no longer boots a listening server as a side effect. This is what makes `runCi`'s self-boot import-safe. @@ -1035,7 +1035,7 @@ releases, deferring version-range CVE matching. Phase 22 closes that gap: SCA exposure across `audit-tree`'s whole dependency graph. - A `known-vulnerability` entry in `REMEDIATIONS` (§3.17/ADR-0031) plus a `vulnerability` `CATEGORY_FALLBACK` entry. -- Adds `semver` (^7.x) as a `@sentinel/core` runtime dependency — the first +- Adds `semver` (^7.x) as a `@agentic-sentinel/core` runtime dependency — the first real semver-range parser in the corpus/rule family. Faithful severity is a deliberate gating stance (diverges from `npm audit`'s @@ -1342,7 +1342,7 @@ which explicitly extends [ADR-0041](./docs/adr/0041-review-hardening.md). --- -## 4. The audit engine (`@sentinel/core`) +## 4. The audit engine (`@agentic-sentinel/core`) Deterministic heuristic core + a pluggable LLM adapter. The score is produced **entirely by the heuristic rules** so it is reproducible and testable; the LLM @@ -1595,8 +1595,8 @@ Five integration modes, all non-invasive: see; a `ProxyClient` failure (unreachable proxy, non-OK response) throws `ProxyError` rather than ever fabricating a verdict, and the MCP layer performs zero scoring of its own (invariant #1 untouched). `parseLockfile` - (used by `sentinel_audit_tree`) moved from `@sentinel/cli` to - `@sentinel/core` this phase so both packages can share it without `mcp` + (used by `sentinel_audit_tree`) moved from `@agentic-sentinel/cli` to + `@agentic-sentinel/core` this phase so both packages can share it without `mcp` tripping `cli`'s own entrypoint guard. The cleanest hook is registry redirection (`.npmrc` `registry=` or `--registry`) diff --git a/CLAUDE.md b/CLAUDE.md index 2ce1d4d..fb7acd7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,7 +29,7 @@ ADR-0045–0048 and threat-model §6. ### Current state by subsystem -**Scoring & rules (`@sentinel/core`)** — 10 registered pure rules +**Scoring & rules (`@agentic-sentinel/core`)** — 10 registered pure rules (`packages/core/src/rules/index.ts`): install-scripts, secret-exfil, network-egress, obfuscation, provenance (ADR-0021/0022), typosquat (ADR-0026), release-anomaly (ADR-0029), known-advisory (ADR-0034), known-vulnerability @@ -52,7 +52,7 @@ at audit time. Also here: multi-format lockfile parsing (npm/yarn/pnpm) + Cyclon 1.6 SBOM export (ADR-0027), `remediate()` advisory fixes (ADR-0031), in-toto/DSSE signed audit attestations (ADR-0032), `lintPolicy` (ADR-0033). -**Proxy (`@sentinel/proxy`)** — sync inline gate over bytes in memory, cached by +**Proxy (`@agentic-sentinel/proxy`)** — sync inline gate over bytes in memory, cached by `dist.integrity`; transparent packument passthrough rewriting only `dist.tarball`. Private-namespace packages are served only from the private store, fail-closed (ADR-0010/0015). `POST /-/audit-tree` whole-lockfile gate with dedupe + 413 cap @@ -75,7 +75,7 @@ configured public base URL off loopback — 421 otherwise (ADR-0036). Byte caps, request coalescing, and an opt-in token-bucket rate limiter round out resource robustness; install-gate paths are never rate-limited (ADR-0037). `packages/proxy/src/index.ts`'s `main()` is entrypoint-guarded — importing -`@sentinel/proxy` must never boot a server as a side effect (ADR-0030). +`@agentic-sentinel/proxy` must never boot a server as a side effect (ADR-0030). Phase 30 generalizes private publishing into an authoritative native write path: pure `source(name, signedPolicy, claimCorpus)` selects policy-private → verified-claim → public-mirror without version merging; native names never fall @@ -109,7 +109,7 @@ it runs each client's exposed mutation commands (Berry has no unpublish; bun has neither dist-tag nor unpublish), while the wire suite covers the complete shared route contract. -**Claim steward (`@sentinel/steward`)** — authenticated operational service for +**Claim steward (`@agentic-sentinel/steward`)** — authenticated operational service for exact-apex DNS TXT challenges, steward-fetched three-tier grandfathering, claimant-key-signed transfers, 12-month renewal and freeze, 30-day announced Tier-2 grants/transfers/dispute rulings, durable atomic state, and atomic @@ -122,7 +122,7 @@ history. The steward control plane and proxy publish route have mandatory per-source rate-limit backstops; release directory names are generated independently of request data. -**Sandbox (`@sentinel/sandbox`)** — `createSandbox()` selects Seatbelt (darwin) +**Sandbox (`@agentic-sentinel/sandbox`)** — `createSandbox()` selects Seatbelt (darwin) or bubblewrap (linux); one approved-capability model, fail-closed contract (ADR-0016/0018). Posture is **deny-by-default**: writes closed except a fixed `writeAllowFloor` + Grants, `$HOME` reads closed except `readAllowList` @@ -146,7 +146,7 @@ outside `exec` remain uncontained (ADR-0051). **CLI / CI / MCP** — `sentinel` CLI: `audit-tree`, `explain`, `stats`/`history`, `policy init|validate|preview|keygen|sign|verify`, `attest-keygen`/`attest`/ -`verify-attestation`, `run-scripts`, `install --enforce`, `exec`. `@sentinel/action` +`verify-attestation`, `run-scripts`, `install --enforce`, `exec`. `@agentic-sentinel/action` (bin `sentinel-ci`) self-boots the proxy in-process for CI, writes SBOM + GitHub-native outputs, idempotent PR comment (ADR-0030). `sentinel-mcp` exposes read tools plus a single write tool that only ever *requests* approval — a human @@ -226,8 +226,8 @@ enforcement is tested with benign probe packages. Node + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`, `mcp`, `action`, `steward` — `action` is the GitHub Action, bin `sentinel-ci`), Express 5, `tar` 7, -`commander` 15, `yaml` 2 (`@sentinel/core` only — pnpm/yarn-berry lockfile -parsing), `semver` 7 (`@sentinel/core` vulnerability range matching), tests on +`commander` 15, `yaml` 2 (`@agentic-sentinel/core` only — pnpm/yarn-berry lockfile +parsing), `semver` 7 (`@agentic-sentinel/core` vulnerability range matching), tests on `node:test` + `tsx`. Developed against **Node 24 (Active LTS)**; Node 22 (Maintenance LTS) also supported — `engines.node` is `>=22`. Pin to current latest; don't downgrade majors without a reason. `node:sqlite` is a built-in, @@ -236,7 +236,7 @@ Node 22 needs `--experimental-sqlite`). The Landlock helper (`packages/sandbox/native/landlock-exec.c`) is compiled by `npm run build` (`build-native.mjs`, Linux + `cc` only, no-op elsewhere) — **never** a `postinstall` hook or lazy runtime compile; both would be posture violations for -a tool that guards against exactly that. The *published* `@sentinel/sandbox` +a tool that guards against exactly that. The *published* `@agentic-sentinel/sandbox` ships the helper as source only (no prebuilt binary in any tarball — enforced by `packages/core/test/package-contents.test.ts`); npm installs opt in via an explicit `node …/scripts/build-native.mjs` (ADR-0052). Releases version all diff --git a/README.md b/README.md index cc842fa..05a7d67 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ has not yet been hardened by production use, and APIs may change without notice. The complete phase-by-phase build log lives in [docs/adr/](./docs/adr/) (one ADR per phase). **Published as an alpha preview**: all seven packages ship as `0.1.0-alpha.1` under the `alpha` -dist-tag (`npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha`) — see +dist-tag (`npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha`) — see the [release notes](./docs/releases/v0.1.0-alpha.1.md) and [release process](./docs/release-process.md); building from source (Quickstart below) remains fully supported. Threat model: @@ -697,7 +697,7 @@ There is no auto-approve or clear-quarantine tool, and none is planned — see ## GitHub Action (Phase 17) -`@sentinel/action` (bin `sentinel-ci`) is a self-contained on-ramp into pull +`@agentic-sentinel/action` (bin `sentinel-ci`) is a self-contained on-ramp into pull requests — it needs no separately-running proxy. `runCi` self-boots the proxy in-process against real npm, audits your lockfile through the same `/-/audit-tree` route the CLI uses, writes a CycloneDX SBOM, and posts the @@ -785,11 +785,11 @@ clear it without weakening detection. ``` packages/ - core/ @sentinel/core audit engine — rules, scoring, data model, LLM adapter (no I/O, fully unit-tested) - proxy/ @sentinel/proxy Express registry proxy, pluggable upstream, audit store, dashboard - cli/ @sentinel/cli pre-install verdicts + registry-redirected npm/npx - mcp/ @sentinel/mcp sentinel-mcp: stdio MCP server, thin client to the proxy (Phase 11) - action/ @sentinel/action sentinel-ci: self-boots the proxy for GitHub Actions (Phase 17) + core/ @agentic-sentinel/core audit engine — rules, scoring, data model, LLM adapter (no I/O, fully unit-tested) + proxy/ @agentic-sentinel/proxy Express registry proxy, pluggable upstream, audit store, dashboard + cli/ @agentic-sentinel/cli pre-install verdicts + registry-redirected npm/npx + mcp/ @agentic-sentinel/mcp sentinel-mcp: stdio MCP server, thin client to the proxy (Phase 11) + action/ @agentic-sentinel/action sentinel-ci: self-boots the proxy for GitHub Actions (Phase 17) fixtures/ benign + synthetic-malicious packages; make-fixtures.ts packs real .tgz tarballs scripts/ make-fixtures.ts, demo.ts ARCHITECTURE.md full design · CLAUDE.md working agreement for this repo diff --git a/SECURITY.md b/SECURITY.md index aa16871..29bd728 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ sandbox for the npm ecosystem. We treat reports against it accordingly. ## Supported versions Sentinel is pre-1.0. Only the tip of `main` and the most recent published -prerelease (`@sentinel/*@alpha`, currently `0.1.0-alpha.1`) are supported; +prerelease (`@agentic-sentinel/*@alpha`, currently `0.1.0-alpha.1`) are supported; there are no maintained release branches. Prereleases are snapshots of `main` — fixes ship as the next prerelease, never as patches to an old one. diff --git a/docs/adr/0052-native-helper-release-packaging.md b/docs/adr/0052-native-helper-release-packaging.md index 2134dc9..ae9afbc 100644 --- a/docs/adr/0052-native-helper-release-packaging.md +++ b/docs/adr/0052-native-helper-release-packaging.md @@ -37,7 +37,7 @@ exfil-tool carve-out unaffected. ## Decision -For `0.1.0-alpha.1`, `@sentinel/sandbox` ships the helper **as source only**, +For `0.1.0-alpha.1`, `@agentic-sentinel/sandbox` ships the helper **as source only**, with an explicit, operator-invoked build path and the documented advisory fallback: @@ -51,7 +51,7 @@ fallback: `scripts/build-native.mjs`. Both are first-party, reviewed files — the same from-source posture ADR-0044 chose over prebuilt distribution. 3. **Compilation is an explicit operator action, never a lifecycle script.** - `node node_modules/@sentinel/sandbox/scripts/build-native.mjs` compiles the + `node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs` compiles the helper in place (Linux + `cc` only; a no-op elsewhere). There is no `postinstall`, no lazy runtime compile, and no network fetch. The package README documents the command and the trade-off. @@ -71,7 +71,7 @@ fallback: ## Alternatives considered -- **Architecture-specific optional packages (`@sentinel/landlock-linux-x64`, +- **Architecture-specific optional packages (`@agentic-sentinel/landlock-linux-x64`, … via `optionalDependencies` + `os`/`cpu`, the esbuild/swc pattern).** The strongest end-state — prebuilt, reproducible, no toolchain requirement — and the likely post-alpha direction. Rejected *for the alpha*: it multiplies the @@ -87,7 +87,7 @@ fallback: x64 artifact silently presented as portable, unreproducible from the tarball, and a standing temptation for the release pipeline to become a binary-injection point. -- **Blocking publication of `@sentinel/sandbox` (and its dependents).** +- **Blocking publication of `@agentic-sentinel/sandbox` (and its dependents).** Unnecessary — ADR-0044's fallback is a designed, tested, honest degradation, not a silent weakening: the notice states the exact residual (a dropped binary can exec but stays filesystem+network confined), and the enforced diff --git a/docs/adr/README.md b/docs/adr/README.md index 3963f0a..548969c 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -145,7 +145,7 @@ first shipped slice; Phases 31 and 32 complete claiming and retraction. | ADR | Title | Decision in one line | |-----|-------|----------------------| | [0051](./0051-sandboxed-exec.md) | Sandboxed `sentinel exec` | `Sandbox.runArgv` (no-shell, execFile-style) + `sentinel exec -- ` reuse the approved-capability model, scrubbed env, and violation telemetry to contain Sentinel-mediated command execution; scoped to explicit invocations only — raw `require()`/`npx` outside it stay uncontained, defense-in-depth behind the ADR-0049 registry gate | -| [0052](./0052-native-helper-release-packaging.md) | Landlock helper release packaging | The published `@sentinel/sandbox` ships the helper as source only (`native/landlock-exec.c` + `build-native.mjs`) — never a prebuilt binary, never a `postinstall` compile; fresh Linux installs run the documented advisory exec floor with a one-time notice until the operator explicitly compiles the helper; enforced by the package-contents test and a missing-helper CI test | +| [0052](./0052-native-helper-release-packaging.md) | Landlock helper release packaging | The published `@agentic-sentinel/sandbox` ships the helper as source only (`native/landlock-exec.c` + `build-native.mjs`) — never a prebuilt binary, never a `postinstall` compile; fresh Linux installs run the documented advisory exec floor with a one-time notice until the operator explicitly compiles the helper; enforced by the package-contents test and a missing-helper CI test | ## Conventions diff --git a/docs/product/registry-roadmap.md b/docs/product/registry-roadmap.md index 04d71d1..d016d4f 100644 --- a/docs/product/registry-roadmap.md +++ b/docs/product/registry-roadmap.md @@ -143,7 +143,7 @@ Evidence: `packages/core/test/claim-corpus.test.ts`, `packages/steward/test/steward.test.ts`. Applicant input cannot select a grandfather tier: the steward owns the upstream lookup, and voluntary transfers must verify against the current claim's Ed25519 key. The proxy remains an -offline consumer; the authenticated `@sentinel/steward` service owns DNS +offline consumer; the authenticated `@agentic-sentinel/steward` service owns DNS verification, durable renewal state, timelocked issuance changes, and signed release output. diff --git a/docs/release-process.md b/docs/release-process.md index 53ca530..201595a 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -11,10 +11,10 @@ Seven workspaces publish under the `@sentinel` scope; the root `sentinel-registry` package is `private` and never publishes. Publication must follow the internal dependency graph: -1. `@sentinel/core` -2. `@sentinel/proxy`, `@sentinel/sandbox`, `@sentinel/mcp`, `@sentinel/steward` -3. `@sentinel/cli` (depends on core + sandbox) -4. `@sentinel/action` (depends on core + proxy) +1. `@agentic-sentinel/core` +2. `@agentic-sentinel/proxy`, `@agentic-sentinel/sandbox`, `@agentic-sentinel/mcp`, `@agentic-sentinel/steward` +3. `@agentic-sentinel/cli` (depends on core + sandbox) +4. `@agentic-sentinel/action` (depends on core + proxy) The release workflow publishes in exactly this order and stops at the first failure without unpublishing anything already released. @@ -27,7 +27,7 @@ failure without unpublishing anything already released. - All seven packages version in lockstep — one release version across the workspace, even for packages with no changes. Lockstep keeps the internal dependency pins trivially correct and the support matrix one-dimensional. -- Internal dependencies are pinned **exact** (`"@sentinel/core": "0.1.0-alpha.1"`, +- Internal dependencies are pinned **exact** (`"@agentic-sentinel/core": "0.1.0-alpha.1"`, no `^`/`~`, never `workspace:*` or `file:` in a published manifest). A prerelease must never float onto a different prerelease. - User-visible hardcoded versions move with the release: @@ -82,7 +82,7 @@ from a PR-triggered workflow. Prefer npm **trusted publishing** (GitHub Actions OIDC) over any long-lived token: configure the repo/workflow as a trusted publisher for each -`@sentinel/*` package on npmjs.com and leave `NPM_TOKEN` unset — npm ≥ 11.5 +`@agentic-sentinel/*` package on npmjs.com and leave `NPM_TOKEN` unset — npm ≥ 11.5 detects OIDC automatically and mints per-publish credentials. Until trusted publishing is configured (it may not be configurable before a package's first publish), use a **granular automation token scoped to the @sentinel @@ -108,10 +108,10 @@ exact commit + workflow run. ## Compromised-release response -1. **Deprecate immediately**: `npm deprecate @sentinel/

@ +1. **Deprecate immediately**: `npm deprecate @agentic-sentinel/

@ "SECURITY: compromised — do not install"` for every affected package. 2. Point the dist-tag at the last known-good version (`npm dist-tag add - @sentinel/

@ alpha`). + @agentic-sentinel/

@ alpha`). 3. Request npm unpublish/security takedown through npm support if within policy; do not rely on it. 4. Rotate every credential the pipeline touched (npm token, corpus/policy diff --git a/docs/releases/v0.1.0-alpha.1.md b/docs/releases/v0.1.0-alpha.1.md index 2a0e04a..38583d2 100644 --- a/docs/releases/v0.1.0-alpha.1.md +++ b/docs/releases/v0.1.0-alpha.1.md @@ -15,27 +15,27 @@ path, a deny-by-default install sandbox, and agent-native tooling. ```bash # CLI + proxy (most users start here) -npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha +npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha sentinel-proxy & # transparent auditing proxy on :4873 sentinel audit is-odd 3.0.1 # pre-install verdict, no code executed sentinel audit-tree package-lock.json --sbom sbom.json # agent hosts (MCP) -npm install -g @sentinel/mcp@alpha +npm install -g @agentic-sentinel/mcp@alpha # library / CI / steward -npm install @sentinel/core@alpha @sentinel/action@alpha @sentinel/steward@alpha +npm install @agentic-sentinel/core@alpha @agentic-sentinel/action@alpha @agentic-sentinel/steward@alpha ``` -All seven packages — `@sentinel/core`, `@sentinel/proxy`, -`@sentinel/sandbox`, `@sentinel/cli`, `@sentinel/mcp`, `@sentinel/steward`, -`@sentinel/action` — publish in lockstep as `0.1.0-alpha.1` under the +All seven packages — `@agentic-sentinel/core`, `@agentic-sentinel/proxy`, +`@agentic-sentinel/sandbox`, `@agentic-sentinel/cli`, `@agentic-sentinel/mcp`, `@agentic-sentinel/steward`, +`@agentic-sentinel/action` — publish in lockstep as `0.1.0-alpha.1` under the `alpha` dist-tag, Apache-2.0, Node ≥ 22. ## What's in this release -**Deterministic audit engine (`@sentinel/core`).** Ten pure heuristic rules +**Deterministic audit engine (`@agentic-sentinel/core`).** Ten pure heuristic rules (install-scripts, secret-exfil, network-egress, obfuscation, provenance, typosquat, release-anomaly, known-advisory, known-vulnerability CVE ranges, and the dataflow-correlated `native-payload-loader`), raw-byte magic @@ -45,7 +45,7 @@ served bytes, npm/yarn/pnpm lockfile parsing, CycloneDX 1.6 SBOM export, and signed DSSE audit attestations. Same input + same policy ⇒ same score, always; the optional LLM adapter can only annotate, never set a verdict. -**Authoritative registry (`@sentinel/proxy`).** A transparent mirror of +**Authoritative registry (`@agentic-sentinel/proxy`).** A transparent mirror of public npm (only `dist.tarball` URLs rewritten) plus a native write path: `npm publish` against Sentinel is audited **synchronously** and gated by signed policy (`publishGate`, default block) before any byte is served. @@ -57,7 +57,7 @@ history), release-cooldown and quarantine serve-time overlays, signed role-token auth, SSRF origin pinning, byte caps, and opt-in SQLite history/metrics. -**Verified namespace steward (`@sentinel/steward`).** Exact-apex DNS TXT +**Verified namespace steward (`@agentic-sentinel/steward`).** Exact-apex DNS TXT claim challenges, three-tier grandfathering against upstream evidence, claimant-key-signed transfers with 30-day timelocks, renewal/freeze lifecycle, and atomic Ed25519-signed claim/retraction corpus releases that @@ -69,7 +69,7 @@ dist-tags, legacy login/whoami, and npm's `-rev` unpublish dance mapped onto time-locked retraction. The compat suite drives the four real client binaries (install, publish, and every mutation each client exposes) in CI. -**Capability sandbox (`@sentinel/sandbox`).** Deny-by-default install-time +**Capability sandbox (`@agentic-sentinel/sandbox`).** Deny-by-default install-time containment behind one approved-capability model: - **macOS (Seatbelt):** fully enforced — write floor, `$HOME` read denial, @@ -82,21 +82,21 @@ containment behind one approved-capability model: does not run lifecycle scripts, by posture). Without the compiled helper the exec floor is **advisory** and announced by a one-time notice; compile it explicitly with - `node node_modules/@sentinel/sandbox/scripts/build-native.mjs` + `node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs` (Linux + `cc`). See ADR-0052. - Any other platform: fail-closed (no sandbox ⇒ enforced operations refuse to run unsandboxed). -**CLI (`@sentinel/cli`).** `sentinel audit`/`audit-tree`/`explain`/`scan`, +**CLI (`@agentic-sentinel/cli`).** `sentinel audit`/`audit-tree`/`explain`/`scan`, registry-redirected `install`/`npx`, sandbox-enforced `install --enforce`, sandboxed one-shot `exec`, policy init/validate/preview/keygen/sign/verify, token minting, attestations, stats/history. -**MCP server (`@sentinel/mcp`).** Stdio Model Context Protocol server for +**MCP server (`@agentic-sentinel/mcp`).** Stdio Model Context Protocol server for agent hosts: six read tools plus one request-only approval tool — an agent can ask, only a human can grant. -**GitHub Action (`@sentinel/action`, bin `sentinel-ci`).** Self-boots the +**GitHub Action (`@agentic-sentinel/action`, bin `sentinel-ci`).** Self-boots the proxy in-process, audits the lockfile, uploads a CycloneDX SBOM, and posts an idempotent PR verdict comment. @@ -124,7 +124,7 @@ an idempotent PR verdict comment. ## Upgrading and feedback Alphas are fix-forward: update with -`npm install -g @sentinel/cli@alpha @sentinel/proxy@alpha` (repeat per +`npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha` (repeat per package) — version numbers are never reused. File bugs, detection gaps, and feature requests at [github.com/git-agentic/pkg-registry/issues](https://github.com/git-agentic/pkg-registry/issues) diff --git a/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md b/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md index 8889d9c..171c546 100644 --- a/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md +++ b/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md @@ -6,7 +6,7 @@ **Architecture:** Three layered deliverables. **A** adds raw-byte magic classification to the extractor and threads the results into rules via a policy-independent `ExtractionObservations` channel. **B** adds an acorn-based `native-payload-loader` rule that correlates READ→DECODE→WRITE→LAUNCH with bounded local dataflow and escalates to critical only when the launched target is taint-reachable from a packaged read. **D** overlays a cooldown block at serve time (no wall-clock in the engine). **E** adds `sentinel exec -- ` running under the existing sandbox. A+B are the first independently shippable milestone; they close the zero-day. -**Tech Stack:** Node 24 + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`), Express 5, `tar` 7, `acorn` + `acorn-walk` (new — `@sentinel/core`'s first parser deps), tests on `node:test` + `tsx`. +**Tech Stack:** Node 24 + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`), Express 5, `tar` 7, `acorn` + `acorn-walk` (new — `@agentic-sentinel/core`'s first parser deps), tests on `node:test` + `tsx`. ## Global Constraints @@ -1241,7 +1241,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; @@ -1448,7 +1448,7 @@ git commit -m "feat(core): releaseCooldown policy field with fail-closed validat import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { cooldownDecision, resolvePublishTime, applyCooldown } from "../src/cooldown.js"; -import type { EnterprisePolicy, AuditReport } from "@sentinel/core"; +import type { EnterprisePolicy, AuditReport } from "@agentic-sentinel/core"; const NOW = Date.parse("2026-07-12T00:00:00Z"); const pol = (cd?: object): EnterprisePolicy => ({ schema: 1, version: "t", scoring: { severityWeight: { info:0,low:4,medium:12,high:25,critical:55 }, diffMultiplier:1.6, thresholds:{allow:80,warn:50}, hardBlockSeverity:"critical" }, rules:{disabled:[]}, allow:[], deny:[], privateNamespaces:[], ...(cd ? { releaseCooldown: cd } : {}) } as EnterprisePolicy); @@ -1506,7 +1506,7 @@ Expected: FAIL — module not found. ```ts // packages/proxy/src/cooldown.ts -import { matchPackage, type AuditReport, type EnterprisePolicy } from "@sentinel/core"; +import { matchPackage, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core"; const HOUR_MS = 3_600_000; @@ -1574,7 +1574,7 @@ Reuse the Task 7 harness verbatim (imports + `ensureFixtures`), but give `startS ```ts // packages/proxy/test/cooldown-e2e.test.ts // (same imports + ensureFixtures + tarballUrl as payload-loader-e2e.test.ts) -import { parsePolicy } from "@sentinel/core"; +import { parsePolicy } from "@agentic-sentinel/core"; // leftpad-lite@1.0.1 carries a fixed `time` in the fixture registry (Step 2 adds it if absent). const PUBLISHED = "2026-07-10T00:00:00Z"; @@ -1854,7 +1854,7 @@ Expected (darwin): FAIL — unknown command `exec`. In `packages/cli/src/index.ts`, add `scrubEnv` to the existing sandbox import (it is already exported from `packages/sandbox/src/index.ts` — no export change needed): ```ts -import { createSandbox, runLifecycleScripts, scrubEnv } from "@sentinel/sandbox"; +import { createSandbox, runLifecycleScripts, scrubEnv } from "@agentic-sentinel/sandbox"; ``` Register the command (near the `run-scripts` command): ```ts diff --git a/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md b/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md index 11ae97a..e7b26ea 100644 --- a/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md +++ b/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md @@ -154,7 +154,7 @@ before UTF-8 conversion**, for **every** file entry regardless of size. New pure rule `packages/core/src/rules/native-payload-loader.ts`, registered in `rules/index.ts`. Adds **acorn** as the first parser dependency of -`@sentinel/core`. +`@agentic-sentinel/core`. ### Primitives (per file, AST-based) diff --git a/package-lock.json b/package-lock.json index 36f671b..df8d999 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,34 @@ "node": ">=22" } }, + "node_modules/@agentic-sentinel/action": { + "resolved": "packages/action", + "link": true + }, + "node_modules/@agentic-sentinel/cli": { + "resolved": "packages/cli", + "link": true + }, + "node_modules/@agentic-sentinel/core": { + "resolved": "packages/core", + "link": true + }, + "node_modules/@agentic-sentinel/mcp": { + "resolved": "packages/mcp", + "link": true + }, + "node_modules/@agentic-sentinel/proxy": { + "resolved": "packages/proxy", + "link": true + }, + "node_modules/@agentic-sentinel/sandbox": { + "resolved": "packages/sandbox", + "link": true + }, + "node_modules/@agentic-sentinel/steward": { + "resolved": "packages/steward", + "link": true + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", @@ -533,34 +561,6 @@ } } }, - "node_modules/@sentinel/action": { - "resolved": "packages/action", - "link": true - }, - "node_modules/@sentinel/cli": { - "resolved": "packages/cli", - "link": true - }, - "node_modules/@sentinel/core": { - "resolved": "packages/core", - "link": true - }, - "node_modules/@sentinel/mcp": { - "resolved": "packages/mcp", - "link": true - }, - "node_modules/@sentinel/proxy": { - "resolved": "packages/proxy", - "link": true - }, - "node_modules/@sentinel/sandbox": { - "resolved": "packages/sandbox", - "link": true - }, - "node_modules/@sentinel/steward": { - "resolved": "packages/steward", - "link": true - }, "node_modules/@sigstore/bundle": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", @@ -2024,12 +2024,12 @@ } }, "packages/action": { - "name": "@sentinel/action", + "name": "@agentic-sentinel/action", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", - "@sentinel/proxy": "0.1.0-alpha.1" + "@agentic-sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/proxy": "0.1.0-alpha.1" }, "bin": { "sentinel-ci": "dist/index.js" @@ -2042,12 +2042,12 @@ } }, "packages/cli": { - "name": "@sentinel/cli", + "name": "@agentic-sentinel/cli", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", - "@sentinel/sandbox": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, "bin": { @@ -2062,7 +2062,7 @@ } }, "packages/core": { - "name": "@sentinel/core", + "name": "@agentic-sentinel/core", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { @@ -2084,12 +2084,12 @@ } }, "packages/mcp": { - "name": "@sentinel/mcp", + "name": "@agentic-sentinel/mcp", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { + "@agentic-sentinel/core": "0.1.0-alpha.1", "@modelcontextprotocol/sdk": "^1.29.0", - "@sentinel/core": "0.1.0-alpha.1", "zod": "^3.23.8" }, "bin": { @@ -2103,11 +2103,11 @@ } }, "packages/proxy": { - "name": "@sentinel/proxy", + "name": "@agentic-sentinel/proxy", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" @@ -2125,11 +2125,11 @@ } }, "packages/sandbox": { - "name": "@sentinel/sandbox", + "name": "@agentic-sentinel/sandbox", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0-alpha.1" + "@agentic-sentinel/core": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" @@ -2139,11 +2139,11 @@ } }, "packages/steward": { - "name": "@sentinel/steward", + "name": "@agentic-sentinel/steward", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, diff --git a/packages/action/README.md b/packages/action/README.md index b45d68b..5753016 100644 --- a/packages/action/README.md +++ b/packages/action/README.md @@ -1,4 +1,4 @@ -# @sentinel/action +# @agentic-sentinel/action `sentinel-ci`: a self-contained CI runner for GitHub Actions. It boots the Sentinel proxy in-process against real npm, audits your lockfile, writes a @@ -9,7 +9,7 @@ idempotent PR comment body — no separately-running proxy needed. > without notice. Not production-ready. ```bash -npm install @sentinel/action@alpha +npm install @agentic-sentinel/action@alpha ``` This package is the engine behind the composite GitHub Action defined at the diff --git a/packages/action/package.json b/packages/action/package.json index b96ce6d..6224de0 100644 --- a/packages/action/package.json +++ b/packages/action/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/action", + "name": "@agentic-sentinel/action", "version": "0.1.0-alpha.1", "description": "Sentinel CI runner: self-booting dependency-tree audit for GitHub Actions (sentinel-ci) — audits a lockfile, writes a CycloneDX SBOM, and posts a PR verdict.", "license": "Apache-2.0", @@ -42,8 +42,8 @@ "sbom" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", - "@sentinel/proxy": "0.1.0-alpha.1" + "@agentic-sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/proxy": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" diff --git a/packages/action/src/index.ts b/packages/action/src/index.ts index e519057..6ec5744 100644 --- a/packages/action/src/index.ts +++ b/packages/action/src/index.ts @@ -1,8 +1,8 @@ #!/usr/bin/env node import { readFileSync, realpathSync } from "node:fs"; import { pathToFileURL } from "node:url"; -import { NpmUpstream, LocalFixtureUpstream, type Upstream } from "@sentinel/proxy"; -import { loadPolicy, DEFAULT_POLICY, type EnterprisePolicy } from "@sentinel/core"; +import { NpmUpstream, LocalFixtureUpstream, type Upstream } from "@agentic-sentinel/proxy"; +import { loadPolicy, DEFAULT_POLICY, type EnterprisePolicy } from "@agentic-sentinel/core"; import { runCi } from "./run.js"; function env(name: string, fallback = ""): string { @@ -47,7 +47,7 @@ async function main(): Promise { } // Run only when invoked as the entrypoint (bin shim or `node dist/index.js`), -// never on import — the same guard as @sentinel/proxy and @sentinel/mcp. +// never on import — the same guard as @agentic-sentinel/proxy and @agentic-sentinel/mcp. function isEntrypoint(): boolean { const arg = process.argv[1]; if (!arg) return false; diff --git a/packages/action/src/report.ts b/packages/action/src/report.ts index 3e89f43..b516fe5 100644 --- a/packages/action/src/report.ts +++ b/packages/action/src/report.ts @@ -1,5 +1,5 @@ -import type { TreeAuditResult, TreePackageRow } from "@sentinel/core"; -import { remediationHint } from "@sentinel/core"; +import type { TreeAuditResult, TreePackageRow } from "@agentic-sentinel/core"; +import { remediationHint } from "@agentic-sentinel/core"; export const REPORT_MARKER = ""; diff --git a/packages/action/src/run.ts b/packages/action/src/run.ts index 1de2953..5fb62ed 100644 --- a/packages/action/src/run.ts +++ b/packages/action/src/run.ts @@ -5,8 +5,8 @@ import type { Server } from "node:http"; import { createServer, AuditStore, ApprovalStore, PrivatePackageStore, ViolationStore, ApprovalRequestStore, type Upstream, -} from "@sentinel/proxy"; -import { parseAnyLockfile, toCycloneDX, DEFAULT_POLICY, type EnterprisePolicy, type TreeAuditResult } from "@sentinel/core"; +} from "@agentic-sentinel/proxy"; +import { parseAnyLockfile, toCycloneDX, DEFAULT_POLICY, type EnterprisePolicy, type TreeAuditResult } from "@agentic-sentinel/core"; import { renderPrComment } from "./report.js"; export interface RunCiOptions { diff --git a/packages/action/test/report.test.ts b/packages/action/test/report.test.ts index cdee620..7f6d5d0 100644 --- a/packages/action/test/report.test.ts +++ b/packages/action/test/report.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { renderPrComment, REPORT_MARKER } from "../src/report.js"; -import type { TreeAuditResult } from "@sentinel/core"; +import type { TreeAuditResult } from "@agentic-sentinel/core"; const result: TreeAuditResult = { aggregate: { diff --git a/packages/action/test/run-e2e.test.ts b/packages/action/test/run-e2e.test.ts index fc62f83..f0f9d19 100644 --- a/packages/action/test/run-e2e.test.ts +++ b/packages/action/test/run-e2e.test.ts @@ -5,7 +5,7 @@ import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; import { describe, test } from "node:test"; -import { LocalFixtureUpstream } from "@sentinel/proxy"; +import { LocalFixtureUpstream } from "@agentic-sentinel/proxy"; import { runCi } from "../src/run.js"; const HERE = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/cli/README.md b/packages/cli/README.md index c096c5c..b586d3c 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,4 +1,4 @@ -# @sentinel/cli +# @agentic-sentinel/cli The Sentinel CLI: pre-install audit verdicts (`sentinel audit`), whole-tree lockfile audits with SBOM export (`sentinel audit-tree`), registry-redirected @@ -10,14 +10,14 @@ authoring/signing, and signed audit attestations. > without notice. Not production-ready. ```bash -npm install -g @sentinel/cli@alpha +npm install -g @agentic-sentinel/cli@alpha sentinel --version -sentinel audit is-odd 3.0.1 # requires a running @sentinel/proxy +sentinel audit is-odd 3.0.1 # requires a running @agentic-sentinel/proxy sentinel audit-tree package-lock.json ``` -Most commands talk to a running [`@sentinel/proxy`](https://www.npmjs.com/package/@sentinel/proxy) +Most commands talk to a running [`@agentic-sentinel/proxy`](https://www.npmjs.com/package/@agentic-sentinel/proxy) (default `http://localhost:4873`, override with `SENTINEL_PROXY` or `-p`). See the [Sentinel repository](https://github.com/git-agentic/pkg-registry) for the full command reference. diff --git a/packages/cli/package.json b/packages/cli/package.json index 2a04827..46ddb0a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/cli", + "name": "@agentic-sentinel/cli", "version": "0.1.0-alpha.1", "description": "Sentinel CLI: pre-install audit verdicts, whole-tree lockfile audits, registry-redirected npm/npx, policy tooling, and sandbox-enforced installs.", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "sandbox" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", - "@sentinel/sandbox": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, "devDependencies": { diff --git a/packages/cli/src/enforce.ts b/packages/cli/src/enforce.ts index 8609742..b130040 100644 --- a/packages/cli/src/enforce.ts +++ b/packages/cli/src/enforce.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import type { Manifest } from "./format.js"; /** Raised when enforcement cannot be guaranteed — the wrapper must fail closed (never run unsandboxed). */ diff --git a/packages/cli/src/format.ts b/packages/cli/src/format.ts index 83ec41a..2fb3f3e 100644 --- a/packages/cli/src/format.ts +++ b/packages/cli/src/format.ts @@ -1,4 +1,4 @@ -import type { AuditReport, Capability, CapabilityKind, Remediation, Severity, Verdict, TreeAuditResult, LintFinding } from "@sentinel/core"; +import type { AuditReport, Capability, CapabilityKind, Remediation, Severity, Verdict, TreeAuditResult, LintFinding } from "@agentic-sentinel/core"; const C = { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 76a2e77..a6bc983 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -18,8 +18,8 @@ import { toCycloneDX, signToken, verifyToken, type Role, buildAuditStatement, signAttestation, verifyAttestation, attestationKeyid, -} from "@sentinel/core"; -import { createSandbox, runLifecycleScripts, scrubEnv } from "@sentinel/sandbox"; +} from "@agentic-sentinel/core"; +import { createSandbox, runLifecycleScripts, scrubEnv } from "@agentic-sentinel/sandbox"; import { formatReport, formatManifest, verdictExitCode, formatTree, treeExitCode, formatViolations, formatStats, formatHistory, formatExplain, formatLint, formatPreview, type Manifest, type ViolationRow, type ExplainResult, type PreviewResult } from "./format.js"; const DEFAULT_PROXY = process.env.SENTINEL_PROXY ?? "http://localhost:4873"; diff --git a/packages/cli/src/script-shell.ts b/packages/cli/src/script-shell.ts index 44900f8..38773b7 100644 --- a/packages/cli/src/script-shell.ts +++ b/packages/cli/src/script-shell.ts @@ -2,9 +2,9 @@ import { homedir } from "node:os"; import { realpathSync } from "node:fs"; import { pathToFileURL } from "node:url"; -import { createSandbox, scrubEnv, resolveProjectRoot } from "@sentinel/sandbox"; -import type { SandboxViolation } from "@sentinel/sandbox"; -import type { Capability } from "@sentinel/core"; +import { createSandbox, scrubEnv, resolveProjectRoot } from "@agentic-sentinel/sandbox"; +import type { SandboxViolation } from "@agentic-sentinel/sandbox"; +import type { Capability } from "@agentic-sentinel/core"; import { approvedCapsForManifest, isRootScript, commandFromArgv, EnforceError } from "./enforce.js"; import { parseApprovals } from "./index.js"; import type { Manifest } from "./format.js"; diff --git a/packages/cli/test/attest-cli-e2e.test.ts b/packages/cli/test/attest-cli-e2e.test.ts index 6b6383e..c5f9e24 100644 --- a/packages/cli/test/attest-cli-e2e.test.ts +++ b/packages/cli/test/attest-cli-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/audit-tree-cli-e2e.test.ts b/packages/cli/test/audit-tree-cli-e2e.test.ts index 5350d81..07a5d40 100644 --- a/packages/cli/test/audit-tree-cli-e2e.test.ts +++ b/packages/cli/test/audit-tree-cli-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/explain-cli-e2e.test.ts b/packages/cli/test/explain-cli-e2e.test.ts index 77f2218..4fb6ad9 100644 --- a/packages/cli/test/explain-cli-e2e.test.ts +++ b/packages/cli/test/explain-cli-e2e.test.ts @@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/format-tree.test.ts b/packages/cli/test/format-tree.test.ts index c8bf02d..1c5fb39 100644 --- a/packages/cli/test/format-tree.test.ts +++ b/packages/cli/test/format-tree.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { TreeAuditResult } from "@sentinel/core"; +import type { TreeAuditResult } from "@agentic-sentinel/core"; import { formatTree, treeExitCode } from "../src/format.js"; const gated: TreeAuditResult = { diff --git a/packages/cli/test/policy-authoring-cli-e2e.test.ts b/packages/cli/test/policy-authoring-cli-e2e.test.ts index 2b6251c..0c9be33 100644 --- a/packages/cli/test/policy-authoring-cli-e2e.test.ts +++ b/packages/cli/test/policy-authoring-cli-e2e.test.ts @@ -10,8 +10,8 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; -import type { AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/policy.test.ts b/packages/cli/test/policy.test.ts index 52b2b39..f16b64c 100644 --- a/packages/cli/test/policy.test.ts +++ b/packages/cli/test/policy.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { summarizePolicy } from "../src/index.js"; describe("summarizePolicy", () => { diff --git a/packages/cli/test/run-scripts.test.ts b/packages/cli/test/run-scripts.test.ts index 2b03a98..e3447fb 100644 --- a/packages/cli/test/run-scripts.test.ts +++ b/packages/cli/test/run-scripts.test.ts @@ -3,7 +3,7 @@ import { mkdtempSync, rmSync, writeFileSync, symlinkSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, test } from "node:test"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import { parseApprovals, unapprovedAtoms, readPackageFiles } from "../src/index.js"; const cap = (kind: string, target: string): Capability => ({ kind: kind as Capability["kind"], target, evidence: [] }); diff --git a/packages/cli/test/stats-history-cli-e2e.test.ts b/packages/cli/test/stats-history-cli-e2e.test.ts index 3dae9ea..b92b794 100644 --- a/packages/cli/test/stats-history-cli-e2e.test.ts +++ b/packages/cli/test/stats-history-cli-e2e.test.ts @@ -8,8 +8,8 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; -import type { AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/core/README.md b/packages/core/README.md index 7b90743..c4a8354 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,4 +1,4 @@ -# @sentinel/core +# @agentic-sentinel/core The Sentinel audit engine: deterministic heuristic rules, scoring, the audit data model, multi-format lockfile parsing (npm/yarn/pnpm), CycloneDX 1.6 SBOM @@ -9,11 +9,11 @@ that can only ever *enrich* — never set — a score. > without notice. Not production-ready. ```bash -npm install @sentinel/core@alpha +npm install @agentic-sentinel/core@alpha ``` ```ts -import { runAudit, score, DEFAULT_POLICY } from "@sentinel/core"; +import { runAudit, score, DEFAULT_POLICY } from "@agentic-sentinel/core"; ``` The engine is fully offline and deterministic: same input + same policy ⇒ same diff --git a/packages/core/package.json b/packages/core/package.json index 8060e6c..f247742 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/core", + "name": "@agentic-sentinel/core", "version": "0.1.0-alpha.1", "description": "Sentinel audit engine: deterministic heuristic rules, scoring, data model, lockfile parsing, SBOM export, and pluggable LLM adapter.", "license": "Apache-2.0", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b5d392e..a2e7e79 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,4 @@ -/** @sentinel/core — deterministic npm package audit engine. */ +/** @agentic-sentinel/core — deterministic npm package audit engine. */ export * from "./types.js"; export { score, severityRank, POLICY_SYNTHESIZED_RULE_IDS } from "./score.js"; diff --git a/packages/core/test/package-contents.test.ts b/packages/core/test/package-contents.test.ts index a8c192d..5a62aee 100644 --- a/packages/core/test/package-contents.test.ts +++ b/packages/core/test/package-contents.test.ts @@ -59,7 +59,7 @@ function packList(pkgDir: string): string[] { } for (const ws of WORKSPACES) { - test(`@sentinel/${ws} tarball contains only runtime files`, () => { + test(`@agentic-sentinel/${ws} tarball contains only runtime files`, () => { const pkgDir = join(repoRoot, "packages", ws); assert.ok( existsSync(join(pkgDir, "dist", "index.js")), @@ -73,10 +73,10 @@ for (const ws of WORKSPACES) { if (re.test(f)) violations.push(`${f} (${name})`); } } - assert.deepEqual(violations, [], `forbidden files in @sentinel/${ws} tarball:\n ${violations.join("\n ")}`); + assert.deepEqual(violations, [], `forbidden files in @agentic-sentinel/${ws} tarball:\n ${violations.join("\n ")}`); for (const req of REQUIRED[ws]) { - assert.ok(files.includes(req), `@sentinel/${ws} tarball is missing required runtime file: ${req}`); + assert.ok(files.includes(req), `@agentic-sentinel/${ws} tarball is missing required runtime file: ${req}`); } }); } diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 75eae3d..6f0cc95 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -1,4 +1,4 @@ -# @sentinel/mcp +# @agentic-sentinel/mcp `sentinel-mcp`: a stdio [Model Context Protocol](https://modelcontextprotocol.io/) server exposing Sentinel's pre-install audit tools to agent hosts. It is a @@ -9,7 +9,7 @@ only write tool *requests* approval; it can never grant one. > without notice. Not production-ready. ```bash -npm install -g @sentinel/mcp@alpha +npm install -g @agentic-sentinel/mcp@alpha ``` MCP client configuration: diff --git a/packages/mcp/package.json b/packages/mcp/package.json index f57a050..3d4ef36 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/mcp", + "name": "@agentic-sentinel/mcp", "version": "0.1.0-alpha.1", "description": "Sentinel MCP server: agent-native pre-install audit tools backed by the Sentinel proxy (stdio Model Context Protocol server).", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "npm-audit" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^3.23.8" }, diff --git a/packages/mcp/src/client.ts b/packages/mcp/src/client.ts index b9c1ecc..4398e45 100644 --- a/packages/mcp/src/client.ts +++ b/packages/mcp/src/client.ts @@ -1,4 +1,4 @@ -import type { AuditReport, Remediation } from "@sentinel/core"; +import type { AuditReport, Remediation } from "@agentic-sentinel/core"; export class ProxyError extends Error { constructor(message: string, readonly status?: number) { diff --git a/packages/mcp/src/format.ts b/packages/mcp/src/format.ts index 671c52a..9a21829 100644 --- a/packages/mcp/src/format.ts +++ b/packages/mcp/src/format.ts @@ -1,4 +1,4 @@ -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; export function summarizeAudit(r: AuditReport, quarantined: boolean): string { const lines = [ diff --git a/packages/mcp/src/tools.ts b/packages/mcp/src/tools.ts index 0f7cda5..84aa00c 100644 --- a/packages/mcp/src/tools.ts +++ b/packages/mcp/src/tools.ts @@ -1,6 +1,6 @@ import { readFileSync } from "node:fs"; import { z } from "zod"; -import { parseLockfile } from "@sentinel/core"; +import { parseLockfile } from "@agentic-sentinel/core"; import type { ProxyClient } from "./client.js"; import { summarizeAudit } from "./format.js"; diff --git a/packages/mcp/test/client-auth.test.ts b/packages/mcp/test/client-auth.test.ts index f711ebb..ffb808b 100644 --- a/packages/mcp/test/client-auth.test.ts +++ b/packages/mcp/test/client-auth.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/client.test.ts b/packages/mcp/test/client.test.ts index 128843b..c46c36b 100644 --- a/packages/mcp/test/client.test.ts +++ b/packages/mcp/test/client.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/server-e2e.test.ts b/packages/mcp/test/server-e2e.test.ts index d6912a4..02447d3 100644 --- a/packages/mcp/test/server-e2e.test.ts +++ b/packages/mcp/test/server-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/tools.test.ts b/packages/mcp/test/tools.test.ts index a986b67..c94ab0b 100644 --- a/packages/mcp/test/tools.test.ts +++ b/packages/mcp/test/tools.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken } from "@agentic-sentinel/core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/proxy/README.md b/packages/proxy/README.md index 578311b..4f24fa3 100644 --- a/packages/proxy/README.md +++ b/packages/proxy/README.md @@ -1,4 +1,4 @@ -# @sentinel/proxy +# @agentic-sentinel/proxy The Sentinel registry proxy: an Express server that transparently serves npm packages while intercepting and auditing every tarball before install-time @@ -10,7 +10,7 @@ npm compatibility surface (packuments, dist-tags, unpublish-as-retraction). > without notice. Not production-ready. ```bash -npm install -g @sentinel/proxy@alpha +npm install -g @agentic-sentinel/proxy@alpha sentinel-proxy # starts the proxy on :4873 ``` diff --git a/packages/proxy/package.json b/packages/proxy/package.json index dc13752..6fdb999 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/proxy", + "name": "@agentic-sentinel/proxy", "version": "0.1.0-alpha.1", "description": "Sentinel registry proxy: transparently serves npm packages while intercepting and auditing each tarball, with an authoritative native publish path, verified claims, and time-locked retraction.", "license": "Apache-2.0", @@ -44,7 +44,7 @@ "package-retraction" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" diff --git a/packages/proxy/src/approval-requests.ts b/packages/proxy/src/approval-requests.ts index 5855a50..38ca194 100644 --- a/packages/proxy/src/approval-requests.ts +++ b/packages/proxy/src/approval-requests.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; export interface ApprovalRequest { name: string; diff --git a/packages/proxy/src/approvals.ts b/packages/proxy/src/approvals.ts index 3e9d637..9baa385 100644 --- a/packages/proxy/src/approvals.ts +++ b/packages/proxy/src/approvals.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import { cmpSemver } from "./upstream.js"; export type ApprovalDecision = "approved" | "denied"; diff --git a/packages/proxy/src/authz.ts b/packages/proxy/src/authz.ts index 61a2d0b..f4f7a98 100644 --- a/packages/proxy/src/authz.ts +++ b/packages/proxy/src/authz.ts @@ -1,5 +1,5 @@ import type { Request, Response, RequestHandler } from "express"; -import { verifyToken, type Role } from "@sentinel/core"; +import { verifyToken, type Role } from "@agentic-sentinel/core"; /** Build the authz layer. `publicKeyPem` undefined ⇒ auth disabled (pass-through). */ export function makeAuthz(publicKeyPem: string | undefined): { enabled: boolean; requireRole(roles: Role[]): RequestHandler } { diff --git a/packages/proxy/src/cooldown.ts b/packages/proxy/src/cooldown.ts index 51cc92a..f6b0e78 100644 --- a/packages/proxy/src/cooldown.ts +++ b/packages/proxy/src/cooldown.ts @@ -1,4 +1,4 @@ -import { matchPackage, type AuditReport, type EnterprisePolicy, type ScoredFinding } from "@sentinel/core"; +import { matchPackage, type AuditReport, type EnterprisePolicy, type ScoredFinding } from "@agentic-sentinel/core"; const HOUR_MS = 3_600_000; diff --git a/packages/proxy/src/history-db.ts b/packages/proxy/src/history-db.ts index 666af65..d38d12a 100644 --- a/packages/proxy/src/history-db.ts +++ b/packages/proxy/src/history-db.ts @@ -1,6 +1,6 @@ import { createRequire } from "node:module"; import { createHash, randomUUID } from "node:crypto"; -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import type { ViolationRecord } from "./violations.js"; export interface HistorySummary { diff --git a/packages/proxy/src/index.ts b/packages/proxy/src/index.ts index 767feeb..f61b5b7 100644 --- a/packages/proxy/src/index.ts +++ b/packages/proxy/src/index.ts @@ -25,7 +25,7 @@ import { type Advisory, type RetractionCorpus, type VulnAdvisory, -} from "@sentinel/core"; +} from "@agentic-sentinel/core"; import { createServer, type ProxyPolicy } from "./server.js"; import { AuditStore } from "./store.js"; import { ApprovalStore } from "./approvals.js"; diff --git a/packages/proxy/src/private-store.ts b/packages/proxy/src/private-store.ts index ebbc19b..4d3cfe0 100644 --- a/packages/proxy/src/private-store.ts +++ b/packages/proxy/src/private-store.ts @@ -2,7 +2,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSy import { createHash, randomUUID } from "node:crypto"; import { join } from "node:path"; import { Buffer } from "node:buffer"; -import type { Audit, RetractionAdvisory, RetractionReason, VerifiedClaim } from "@sentinel/core"; +import type { Audit, RetractionAdvisory, RetractionReason, VerifiedClaim } from "@agentic-sentinel/core"; import { cmpSemver } from "./upstream.js"; export interface StoredVersion { @@ -32,7 +32,7 @@ export interface PrivatePackument { _sentinel?: { retractions: Record }; } -export type { RetractionAdvisory, RetractionReason } from "@sentinel/core"; +export type { RetractionAdvisory, RetractionReason } from "@agentic-sentinel/core"; export interface RetractionTombstone { retractedAt: string; diff --git a/packages/proxy/src/reconcile.ts b/packages/proxy/src/reconcile.ts index 3655a6f..13b0258 100644 --- a/packages/proxy/src/reconcile.ts +++ b/packages/proxy/src/reconcile.ts @@ -1,4 +1,4 @@ -import { capabilityAtom, type Capability } from "@sentinel/core"; +import { capabilityAtom, type Capability } from "@agentic-sentinel/core"; import type { Approval } from "./approvals.js"; export type ApprovalState = "approved" | "inherited" | "required" | "denied" | "n-a"; diff --git a/packages/proxy/src/registry-mode.ts b/packages/proxy/src/registry-mode.ts index e97ab3a..15c7e9b 100644 --- a/packages/proxy/src/registry-mode.ts +++ b/packages/proxy/src/registry-mode.ts @@ -1,5 +1,5 @@ import { writeFileSync } from "node:fs"; -import type { ClaimCorpus, EnterprisePolicy } from "@sentinel/core"; +import type { ClaimCorpus, EnterprisePolicy } from "@agentic-sentinel/core"; import type { PrivatePackageStore } from "./private-store.js"; import { EMPTY_CLAIM_CORPUS, source } from "./resolution.js"; import type { RegistryMode } from "./server.js"; diff --git a/packages/proxy/src/resolution.ts b/packages/proxy/src/resolution.ts index ebb6e61..e77abbf 100644 --- a/packages/proxy/src/resolution.ts +++ b/packages/proxy/src/resolution.ts @@ -6,10 +6,10 @@ import { type EnterprisePolicy, type ProvenanceIdentity, type VerifiedClaim, -} from "@sentinel/core"; +} from "@agentic-sentinel/core"; -export { EMPTY_CLAIM_CORPUS } from "@sentinel/core"; -export type { ClaimCorpus, VerifiedClaim } from "@sentinel/core"; +export { EMPTY_CLAIM_CORPUS } from "@agentic-sentinel/core"; +export type { ClaimCorpus, VerifiedClaim } from "@agentic-sentinel/core"; export type RegistrySource = "policy-private" | "verified-claim" | "public-mirror"; diff --git a/packages/proxy/src/server.ts b/packages/proxy/src/server.ts index 9245029..e2efea7 100644 --- a/packages/proxy/src/server.ts +++ b/packages/proxy/src/server.ts @@ -37,7 +37,7 @@ import { type RetractionAdvisory, type RetractionCorpus, type RetractionReason, -} from "@sentinel/core"; +} from "@agentic-sentinel/core"; import { AuditStore } from "./store.js"; import { resolvePublishTime, cooldownDecision, applyCooldown, blockOverlay } from "./cooldown.js"; import { diff --git a/packages/proxy/src/store.ts b/packages/proxy/src/store.ts index e1eb9ad..25175ca 100644 --- a/packages/proxy/src/store.ts +++ b/packages/proxy/src/store.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import type { HistoryDb } from "./history-db.js"; export interface StoredAudit { diff --git a/packages/proxy/src/upstream.ts b/packages/proxy/src/upstream.ts index c27d6a4..a2a8023 100644 --- a/packages/proxy/src/upstream.ts +++ b/packages/proxy/src/upstream.ts @@ -4,7 +4,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { request as httpRequest } from "node:http"; import { request as httpsRequest } from "node:https"; -import type { RegistrySignature } from "@sentinel/core"; +import type { RegistrySignature } from "@agentic-sentinel/core"; import { assertAllowedTarballUrl } from "./net-config.js"; import { readBodyCapped } from "./limits.js"; diff --git a/packages/proxy/test/approval-requests-e2e.test.ts b/packages/proxy/test/approval-requests-e2e.test.ts index adfd488..8e8204f 100644 --- a/packages/proxy/test/approval-requests-e2e.test.ts +++ b/packages/proxy/test/approval-requests-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-e2e.test.ts b/packages/proxy/test/audit-tree-e2e.test.ts index 5b8036e..ea9f7bf 100644 --- a/packages/proxy/test/audit-tree-e2e.test.ts +++ b/packages/proxy/test/audit-tree-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-integrity-e2e.test.ts b/packages/proxy/test/audit-tree-integrity-e2e.test.ts index bfa3e6a..aa65fdb 100644 --- a/packages/proxy/test/audit-tree-integrity-e2e.test.ts +++ b/packages/proxy/test/audit-tree-integrity-e2e.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type TreeAuditResult } from "@sentinel/core"; +import { DEFAULT_POLICY, type TreeAuditResult } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-limits-e2e.test.ts b/packages/proxy/test/audit-tree-limits-e2e.test.ts index 936a94d..e920361 100644 --- a/packages/proxy/test/audit-tree-limits-e2e.test.ts +++ b/packages/proxy/test/audit-tree-limits-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/auth-config.test.ts b/packages/proxy/test/auth-config.test.ts index 7f5b660..cb92bc9 100644 --- a/packages/proxy/test/auth-config.test.ts +++ b/packages/proxy/test/auth-config.test.ts @@ -7,7 +7,7 @@ import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; import { describe, test } from "node:test"; -import { generateKeypair } from "@sentinel/core"; +import { generateKeypair } from "@agentic-sentinel/core"; import { validateAuthPublicKey } from "../src/auth-config.js"; const execFileAsync = promisify(execFile); diff --git a/packages/proxy/test/authz-e2e.test.ts b/packages/proxy/test/authz-e2e.test.ts index b76055e..cfdabf6 100644 --- a/packages/proxy/test/authz-e2e.test.ts +++ b/packages/proxy/test/authz-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/authz-unit.test.ts b/packages/proxy/test/authz-unit.test.ts index d37a93a..0d7c373 100644 --- a/packages/proxy/test/authz-unit.test.ts +++ b/packages/proxy/test/authz-unit.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { generateKeypair, signToken, type Role } from "@sentinel/core"; +import { generateKeypair, signToken, type Role } from "@agentic-sentinel/core"; import { makeAuthz } from "../src/authz.js"; const { publicKey, privateKey } = generateKeypair(); diff --git a/packages/proxy/test/claim-corpus-startup.test.ts b/packages/proxy/test/claim-corpus-startup.test.ts index 28d49ee..5247f00 100644 --- a/packages/proxy/test/claim-corpus-startup.test.ts +++ b/packages/proxy/test/claim-corpus-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, signClaimCorpus, signRetractionCorpus } from "@sentinel/core"; +import { generateKeypair, signClaimCorpus, signRetractionCorpus } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const ROOT = join(HERE, "..", "..", ".."); diff --git a/packages/proxy/test/claim-lifecycle-e2e.test.ts b/packages/proxy/test/claim-lifecycle-e2e.test.ts index 5f4aab1..a76808c 100644 --- a/packages/proxy/test/claim-lifecycle-e2e.test.ts +++ b/packages/proxy/test/claim-lifecycle-e2e.test.ts @@ -7,7 +7,7 @@ import type { AddressInfo } from "node:net"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { afterEach, describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, runAudit, type ClaimCorpus, type ClaimStatus, type EnterprisePolicy, type TrustedPublisher } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, runAudit, type ClaimCorpus, type ClaimStatus, type EnterprisePolicy, type TrustedPublisher } from "@agentic-sentinel/core"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { ApprovalStore } from "../src/approvals.js"; import { PrivatePackageStore } from "../src/private-store.js"; diff --git a/packages/proxy/test/coalesce-e2e.test.ts b/packages/proxy/test/coalesce-e2e.test.ts index 5672118..d5eeb3f 100644 --- a/packages/proxy/test/coalesce-e2e.test.ts +++ b/packages/proxy/test/coalesce-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/compatibility-e2e.test.ts b/packages/proxy/test/compatibility-e2e.test.ts index f46036f..ea5e6c5 100644 --- a/packages/proxy/test/compatibility-e2e.test.ts +++ b/packages/proxy/test/compatibility-e2e.test.ts @@ -6,7 +6,7 @@ import { after, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; import { gzipSync } from "node:zlib"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, integrityOfAlgo, runAudit, signToken, type ClaimCorpus, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, integrityOfAlgo, runAudit, signToken, type ClaimCorpus, type EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { ApprovalStore } from "../src/approvals.js"; diff --git a/packages/proxy/test/cooldown-e2e.test.ts b/packages/proxy/test/cooldown-e2e.test.ts index b3d76ba..3ea8ac2 100644 --- a/packages/proxy/test/cooldown-e2e.test.ts +++ b/packages/proxy/test/cooldown-e2e.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { parsePolicy } from "@sentinel/core"; +import { parsePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/cooldown.test.ts b/packages/proxy/test/cooldown.test.ts index d9669b5..4e8ba5b 100644 --- a/packages/proxy/test/cooldown.test.ts +++ b/packages/proxy/test/cooldown.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { cooldownDecision, resolvePublishTime, applyCooldown, blockOverlay } from "../src/cooldown.js"; -import type { EnterprisePolicy, AuditReport } from "@sentinel/core"; +import type { EnterprisePolicy, AuditReport } from "@agentic-sentinel/core"; const NOW = Date.parse("2026-07-12T00:00:00Z"); diff --git a/packages/proxy/test/enforce-e2e.test.ts b/packages/proxy/test/enforce-e2e.test.ts index f25c211..114dbd2 100644 --- a/packages/proxy/test/enforce-e2e.test.ts +++ b/packages/proxy/test/enforce-e2e.test.ts @@ -14,7 +14,7 @@ import { ApprovalStore } from "../src/approvals.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/explain-e2e.test.ts b/packages/proxy/test/explain-e2e.test.ts index 786836d..0e07a71 100644 --- a/packages/proxy/test/explain-e2e.test.ts +++ b/packages/proxy/test/explain-e2e.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, runAudit, integrityOf, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, runAudit, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/history-db-queries.test.ts b/packages/proxy/test/history-db-queries.test.ts index 772be06..f9eb715 100644 --- a/packages/proxy/test/history-db-queries.test.ts +++ b/packages/proxy/test/history-db-queries.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import type { ViolationRecord } from "../src/violations.js"; function rep(integrity: string, name: string, verdict: "allow" | "warn" | "block", finding: string | null, at: string): [AuditReport, string] { diff --git a/packages/proxy/test/history-db.test.ts b/packages/proxy/test/history-db.test.ts index 0837d4e..1ae875f 100644 --- a/packages/proxy/test/history-db.test.ts +++ b/packages/proxy/test/history-db.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import type { ViolationRecord } from "../src/violations.js"; function auditReport(over: Partial<{ integrity: string; name: string; version: string; verdict: "allow" | "warn" | "block"; score: number; finding: string; signature: string; provenance: string }> = {}): AuditReport { diff --git a/packages/proxy/test/history-endpoints-e2e.test.ts b/packages/proxy/test/history-endpoints-e2e.test.ts index 629befc..fb86be0 100644 --- a/packages/proxy/test/history-endpoints-e2e.test.ts +++ b/packages/proxy/test/history-endpoints-e2e.test.ts @@ -2,8 +2,8 @@ import assert from "node:assert/strict"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; -import type { AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/history-writethrough.test.ts b/packages/proxy/test/history-writethrough.test.ts index fe0dea6..e180178 100644 --- a/packages/proxy/test/history-writethrough.test.ts +++ b/packages/proxy/test/history-writethrough.test.ts @@ -3,7 +3,7 @@ import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; import { AuditStore } from "../src/store.js"; import { ViolationStore } from "../src/violations.js"; -import type { AuditReport } from "@sentinel/core"; +import type { AuditReport } from "@agentic-sentinel/core"; import type { ViolationRecord } from "../src/violations.js"; const report = { diff --git a/packages/proxy/test/known-advisory-e2e.test.ts b/packages/proxy/test/known-advisory-e2e.test.ts index 9adb4ef..c9b8c57 100644 --- a/packages/proxy/test/known-advisory-e2e.test.ts +++ b/packages/proxy/test/known-advisory-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type Advisory, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type Advisory, type AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/known-vulnerability-e2e.test.ts b/packages/proxy/test/known-vulnerability-e2e.test.ts index 31d26a9..df311dd 100644 --- a/packages/proxy/test/known-vulnerability-e2e.test.ts +++ b/packages/proxy/test/known-vulnerability-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type VulnAdvisory, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type VulnAdvisory, type AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/payload-loader-e2e.test.ts b/packages/proxy/test/payload-loader-e2e.test.ts index 67b357e..33240e0 100644 --- a/packages/proxy/test/payload-loader-e2e.test.ts +++ b/packages/proxy/test/payload-loader-e2e.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/policy-preview-e2e.test.ts b/packages/proxy/test/policy-preview-e2e.test.ts index 2d1b2c8..e8b1329 100644 --- a/packages/proxy/test/policy-preview-e2e.test.ts +++ b/packages/proxy/test/policy-preview-e2e.test.ts @@ -2,8 +2,8 @@ import assert from "node:assert/strict"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, score } from "@sentinel/core"; -import type { Audit, AuditReport, EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, score } from "@agentic-sentinel/core"; +import type { Audit, AuditReport, EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/policy-startup.test.ts b/packages/proxy/test/policy-startup.test.ts index 0f5a6be..497ec97 100644 --- a/packages/proxy/test/policy-startup.test.ts +++ b/packages/proxy/test/policy-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, signPolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signPolicy } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = join(HERE, "..", "..", ".."); diff --git a/packages/proxy/test/private-serve.test.ts b/packages/proxy/test/private-serve.test.ts index bf966aa..7faf36c 100644 --- a/packages/proxy/test/private-serve.test.ts +++ b/packages/proxy/test/private-serve.test.ts @@ -14,7 +14,7 @@ import { PrivatePackageStore } from "../src/private-store.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { LocalFixtureUpstream, type Upstream } from "../src/upstream.js"; -import { DEFAULT_POLICY, generateKeypair, runAudit, integrityOf, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, runAudit, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/private-store.test.ts b/packages/proxy/test/private-store.test.ts index 6c050c5..97b9401 100644 --- a/packages/proxy/test/private-store.test.ts +++ b/packages/proxy/test/private-store.test.ts @@ -5,7 +5,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, test } from "node:test"; import { PrivatePackageStore } from "../src/private-store.js"; -import type { Audit } from "@sentinel/core"; +import type { Audit } from "@agentic-sentinel/core"; const audit = { schema: 3, meta: {}, findings: [], capabilities: [], capabilityDelta: null, engine: { version: "x", rules: [], mode: "full" }, auditedAt: "t", durationMs: 0 } as unknown as Audit; diff --git a/packages/proxy/test/provenance-verify.test.ts b/packages/proxy/test/provenance-verify.test.ts index 65ca46c..4d1c823 100644 --- a/packages/proxy/test/provenance-verify.test.ts +++ b/packages/proxy/test/provenance-verify.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type EnterprisePolicy, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type EnterprisePolicy, type AuditReport } from "@agentic-sentinel/core"; import { createServer, type ServerOptions } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/proxy.test.ts b/packages/proxy/test/proxy.test.ts index 5408644..22308ed 100644 --- a/packages/proxy/test/proxy.test.ts +++ b/packages/proxy/test/proxy.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, type EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/public-base-url-e2e.test.ts b/packages/proxy/test/public-base-url-e2e.test.ts index 1df2090..33d57bf 100644 --- a/packages/proxy/test/public-base-url-e2e.test.ts +++ b/packages/proxy/test/public-base-url-e2e.test.ts @@ -7,7 +7,7 @@ import { request as httpRequest } from "node:http"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/publish.test.ts b/packages/proxy/test/publish.test.ts index c2ae387..0482631 100644 --- a/packages/proxy/test/publish.test.ts +++ b/packages/proxy/test/publish.test.ts @@ -18,7 +18,7 @@ import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import type { ClaimCorpus } from "../src/resolution.js"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/rate-limit-e2e.test.ts b/packages/proxy/test/rate-limit-e2e.test.ts index ee5d516..b10f658 100644 --- a/packages/proxy/test/rate-limit-e2e.test.ts +++ b/packages/proxy/test/rate-limit-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { createRateLimiter } from "../src/rate-limit.js"; import { AuditStore } from "../src/store.js"; diff --git a/packages/proxy/test/reconcile.test.ts b/packages/proxy/test/reconcile.test.ts index 0f4a67c..11cfc98 100644 --- a/packages/proxy/test/reconcile.test.ts +++ b/packages/proxy/test/reconcile.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import { reconcileApproval } from "../src/reconcile.js"; import type { Approval } from "../src/approvals.js"; diff --git a/packages/proxy/test/registry-migration.test.ts b/packages/proxy/test/registry-migration.test.ts index 98f24a1..1e0d5ba 100644 --- a/packages/proxy/test/registry-migration.test.ts +++ b/packages/proxy/test/registry-migration.test.ts @@ -8,7 +8,7 @@ import { join } from "node:path"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, type Audit, type ClaimCorpus } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, type Audit, type ClaimCorpus } from "@agentic-sentinel/core"; import { PrivatePackageStore } from "../src/private-store.js"; import { configureRegistryMode } from "../src/registry-mode.js"; import { exportNativeStore } from "../src/registry-export.js"; diff --git a/packages/proxy/test/registry-mode-startup.test.ts b/packages/proxy/test/registry-mode-startup.test.ts index c0c9374..2f7d159 100644 --- a/packages/proxy/test/registry-mode-startup.test.ts +++ b/packages/proxy/test/registry-mode-startup.test.ts @@ -5,7 +5,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, signClaimCorpus, type Audit } from "@sentinel/core"; +import { generateKeypair, signClaimCorpus, type Audit } from "@agentic-sentinel/core"; import { PrivatePackageStore } from "../src/private-store.js"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", ".."); diff --git a/packages/proxy/test/release-anomaly-e2e.test.ts b/packages/proxy/test/release-anomaly-e2e.test.ts index 20b6f13..72a368f 100644 --- a/packages/proxy/test/release-anomaly-e2e.test.ts +++ b/packages/proxy/test/release-anomaly-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/resolution.test.ts b/packages/proxy/test/resolution.test.ts index 693dba2..0323d60 100644 --- a/packages/proxy/test/resolution.test.ts +++ b/packages/proxy/test/resolution.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, type EnterprisePolicy } from "@agentic-sentinel/core"; import { EMPTY_CLAIM_CORPUS, normalizePackageName, diff --git a/packages/proxy/test/retraction-e2e.test.ts b/packages/proxy/test/retraction-e2e.test.ts index adac5fe..13f4343 100644 --- a/packages/proxy/test/retraction-e2e.test.ts +++ b/packages/proxy/test/retraction-e2e.test.ts @@ -3,7 +3,7 @@ import { Buffer } from "node:buffer"; import type { Server } from "node:http"; import type { AddressInfo } from "node:net"; import { afterEach, describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, retractionCorpusHashOfBytes, signToken, type Audit, type EnterprisePolicy, type RetractionCorpus } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, retractionCorpusHashOfBytes, signToken, type Audit, type EnterprisePolicy, type RetractionCorpus } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { ApprovalStore } from "../src/approvals.js"; diff --git a/packages/proxy/test/signature-verify.test.ts b/packages/proxy/test/signature-verify.test.ts index d2eb3ec..0c022d0 100644 --- a/packages/proxy/test/signature-verify.test.ts +++ b/packages/proxy/test/signature-verify.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type NpmSigningKey } from "@sentinel/core"; +import { DEFAULT_POLICY, type NpmSigningKey } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/tree.test.ts b/packages/proxy/test/tree.test.ts index 57f33f7..b26cb07 100644 --- a/packages/proxy/test/tree.test.ts +++ b/packages/proxy/test/tree.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type TreeAuditResult } from "@sentinel/core"; +import { DEFAULT_POLICY, type TreeAuditResult } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/typosquat-e2e.test.ts b/packages/proxy/test/typosquat-e2e.test.ts index bfa95de..6fa840f 100644 --- a/packages/proxy/test/typosquat-e2e.test.ts +++ b/packages/proxy/test/typosquat-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/violation-enforce-e2e.test.ts b/packages/proxy/test/violation-enforce-e2e.test.ts index e727e65..805a611 100644 --- a/packages/proxy/test/violation-enforce-e2e.test.ts +++ b/packages/proxy/test/violation-enforce-e2e.test.ts @@ -26,7 +26,7 @@ import { ApprovalStore } from "../src/approvals.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport } from "@agentic-sentinel/core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/violations-e2e.test.ts b/packages/proxy/test/violations-e2e.test.ts index b98dd7f..c8d3f03 100644 --- a/packages/proxy/test/violations-e2e.test.ts +++ b/packages/proxy/test/violations-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@agentic-sentinel/core"; import { createServer, type ServerOptions } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/violations-startup.test.ts b/packages/proxy/test/violations-startup.test.ts index d22686f..8eb963f 100644 --- a/packages/proxy/test/violations-startup.test.ts +++ b/packages/proxy/test/violations-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair } from "@sentinel/core"; +import { generateKeypair } from "@agentic-sentinel/core"; const execFileAsync = promisify(execFile); const HERE = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/sandbox/README.md b/packages/sandbox/README.md index 3eff264..2c14ee1 100644 --- a/packages/sandbox/README.md +++ b/packages/sandbox/README.md @@ -1,4 +1,4 @@ -# @sentinel/sandbox +# @agentic-sentinel/sandbox The Sentinel capability sandbox: turns an approved capability set into enforced install-time least-privilege. `createSandbox()` selects **Seatbelt** @@ -10,7 +10,7 @@ with a fail-closed contract on any other platform. > without notice. Not production-ready. ```bash -npm install @sentinel/sandbox@alpha +npm install @agentic-sentinel/sandbox@alpha ``` ## Platform behavior in this alpha @@ -29,7 +29,7 @@ To opt in to Landlock exec-floor enforcement on Linux, compile the helper explicitly (requires `cc`): ```bash -node node_modules/@sentinel/sandbox/scripts/build-native.mjs +node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs ``` The helper is verified with an ABI probe before use; any failure falls back diff --git a/packages/sandbox/package.json b/packages/sandbox/package.json index df73b9f..3702531 100644 --- a/packages/sandbox/package.json +++ b/packages/sandbox/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/sandbox", + "name": "@agentic-sentinel/sandbox", "version": "0.1.0-alpha.1", "description": "Sentinel capability sandbox: generate an OS sandbox profile from approved capabilities and run lifecycle scripts under it (macOS Seatbelt / Linux bubblewrap, deny-by-default).", "license": "Apache-2.0", @@ -43,7 +43,7 @@ "least-privilege" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1" + "@agentic-sentinel/core": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" diff --git a/packages/sandbox/src/bubblewrap.ts b/packages/sandbox/src/bubblewrap.ts index 16657f1..9277e77 100644 --- a/packages/sandbox/src/bubblewrap.ts +++ b/packages/sandbox/src/bubblewrap.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from "node:url"; import { dirname, join, sep } from "node:path"; import { generateBwrapArgs } from "./bwrap.js"; import type { Sandbox, SandboxResult } from "./types.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import { computeDenySet, landlockAllowPaths } from "./deny-set.js"; import { classifyViolation } from "./violation.js"; import { nodeInstallPrefix } from "./read-allow.js"; diff --git a/packages/sandbox/src/bwrap.ts b/packages/sandbox/src/bwrap.ts index d659da8..e85885b 100644 --- a/packages/sandbox/src/bwrap.ts +++ b/packages/sandbox/src/bwrap.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@sentinel/core"; +import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; import { pathCovers } from "./path-cover.js"; import { expandHome, isSafeGrantTarget } from "./deny-set.js"; import { writeAllowFloor } from "./write-floor.js"; diff --git a/packages/sandbox/src/deny-set.ts b/packages/sandbox/src/deny-set.ts index 2cf55e8..818e794 100644 --- a/packages/sandbox/src/deny-set.ts +++ b/packages/sandbox/src/deny-set.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@sentinel/core"; +import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; import { pathCovers } from "./path-cover.js"; import { execAllowFloor, linuxExecFloor } from "./exec-floor.js"; import { SENSITIVE_EXECUTABLES, execCarveOutPaths, classifyProcessTarget } from "./sensitive-executables.js"; diff --git a/packages/sandbox/src/env.ts b/packages/sandbox/src/env.ts index 87acb7f..777ba89 100644 --- a/packages/sandbox/src/env.ts +++ b/packages/sandbox/src/env.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; /** Env-var names that look credential-bearing — dropped regardless of allowlist match. */ export const CREDENTIAL_ENV_RE = /_auth|authtoken|_password|passwd|token|secret|credential|api[_-]?key|access[_-]?key/i; diff --git a/packages/sandbox/src/profile.ts b/packages/sandbox/src/profile.ts index 1a4e3b8..be12e2b 100644 --- a/packages/sandbox/src/profile.ts +++ b/packages/sandbox/src/profile.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@sentinel/core"; +import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; import { pathCovers } from "./path-cover.js"; import { canonicalizeMacPath, expandHome, isSafeGrantTarget } from "./deny-set.js"; import { writeAllowFloor } from "./write-floor.js"; diff --git a/packages/sandbox/src/runner.ts b/packages/sandbox/src/runner.ts index 488c83e..75fe630 100644 --- a/packages/sandbox/src/runner.ts +++ b/packages/sandbox/src/runner.ts @@ -2,7 +2,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import type { Sandbox } from "./types.js"; import { scrubEnv } from "./env.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; export interface ScriptResult { hook: string; diff --git a/packages/sandbox/src/seatbelt.ts b/packages/sandbox/src/seatbelt.ts index 473a976..4831ba4 100644 --- a/packages/sandbox/src/seatbelt.ts +++ b/packages/sandbox/src/seatbelt.ts @@ -2,7 +2,7 @@ import { spawnSync } from "node:child_process"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import type { Sandbox, SandboxResult } from "./types.js"; import { generateProfile } from "./profile.js"; import { computeDenySet } from "./deny-set.js"; diff --git a/packages/sandbox/src/types.ts b/packages/sandbox/src/types.ts index c89ce9a..486cb79 100644 --- a/packages/sandbox/src/types.ts +++ b/packages/sandbox/src/types.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; export interface SandboxViolation { /** The denied resource class the child hit. */ diff --git a/packages/sandbox/test/bubblewrap.test.ts b/packages/sandbox/test/bubblewrap.test.ts index f14ef70..1abd9c5 100644 --- a/packages/sandbox/test/bubblewrap.test.ts +++ b/packages/sandbox/test/bubblewrap.test.ts @@ -9,7 +9,7 @@ import { describe, test } from "node:test"; import { BubblewrapSandbox } from "../src/bubblewrap.js"; import { runLifecycleScripts } from "../src/runner.js"; import { scrubEnv } from "../src/env.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; // dist sibling of the compiled bubblewrap.js; in the source tree the helper lands in // packages/sandbox/dist/landlock-exec after `npm run build`. @@ -304,7 +304,7 @@ describe("BubblewrapSandbox enforcement", { skip }, () => { }); test("missing Landlock helper: scripts still run on the advisory floor with a one-time notice (packaged-artifact state)", () => { - // The published @sentinel/sandbox tarball deliberately ships NO compiled + // The published @agentic-sentinel/sandbox tarball deliberately ships NO compiled // landlock-exec (source-only, no lifecycle-script compile). Reproduce that // state hermetically: copy the built dist/ WITHOUT the helper binary and // drive bubblewrap.js from the copy — its helper lookup (same-dir sibling) diff --git a/packages/sandbox/test/bwrap.test.ts b/packages/sandbox/test/bwrap.test.ts index b3d7bfc..3bbae4d 100644 --- a/packages/sandbox/test/bwrap.test.ts +++ b/packages/sandbox/test/bwrap.test.ts @@ -2,7 +2,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { generateBwrapArgs } from "../src/bwrap.js"; import { SENSITIVE_EXECUTABLES } from "../src/sensitive-executables.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; const fs = (target: string): Capability => ({ kind: "filesystem", target, evidence: [] }); const net = (target: string): Capability => ({ kind: "network", target, evidence: [] }); diff --git a/packages/sandbox/test/deny-set.test.ts b/packages/sandbox/test/deny-set.test.ts index 35d7507..7142b04 100644 --- a/packages/sandbox/test/deny-set.test.ts +++ b/packages/sandbox/test/deny-set.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; import { computeDenySet, isSafeGrantTarget, landlockAllowPaths } from "../src/deny-set.js"; import { generateProfile } from "../src/profile.js"; import { generateBwrapArgs } from "../src/bwrap.js"; diff --git a/packages/sandbox/test/env.test.ts b/packages/sandbox/test/env.test.ts index b3cb47c..a4549ba 100644 --- a/packages/sandbox/test/env.test.ts +++ b/packages/sandbox/test/env.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { scrubEnv, ENV_ALLOWLIST, CREDENTIAL_ENV_RE } from "../src/env.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; const envCap = (target: string): Capability => ({ kind: "env", target, evidence: [] }); diff --git a/packages/sandbox/test/profile.test.ts b/packages/sandbox/test/profile.test.ts index bbca6fd..acec9e0 100644 --- a/packages/sandbox/test/profile.test.ts +++ b/packages/sandbox/test/profile.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { generateProfile } from "../src/profile.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; const fs = (target: string): Capability => ({ kind: "filesystem", target, evidence: [] }); const net = (target: string): Capability => ({ kind: "network", target, evidence: [] }); diff --git a/packages/sandbox/test/runner.test.ts b/packages/sandbox/test/runner.test.ts index 4d54534..4953f70 100644 --- a/packages/sandbox/test/runner.test.ts +++ b/packages/sandbox/test/runner.test.ts @@ -5,7 +5,7 @@ import { join } from "node:path"; import { describe, test } from "node:test"; import { runLifecycleScripts } from "../src/runner.js"; import type { Sandbox, SandboxResult } from "../src/types.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; function fakeSandbox(captured: NodeJS.ProcessEnv[]): Sandbox { return { run(_cmd, opts: { cwd: string; approved: Capability[]; homeDir: string; env?: NodeJS.ProcessEnv }): SandboxResult { diff --git a/packages/sandbox/test/seatbelt.test.ts b/packages/sandbox/test/seatbelt.test.ts index e9c3028..91f4eed 100644 --- a/packages/sandbox/test/seatbelt.test.ts +++ b/packages/sandbox/test/seatbelt.test.ts @@ -7,7 +7,7 @@ import { describe, test } from "node:test"; import { SeatbeltSandbox } from "../src/seatbelt.js"; import { runLifecycleScripts } from "../src/runner.js"; import { scrubEnv } from "../src/env.js"; -import type { Capability } from "@sentinel/core"; +import type { Capability } from "@agentic-sentinel/core"; const darwin = process.platform === "darwin"; diff --git a/packages/steward/README.md b/packages/steward/README.md index aba695b..3417478 100644 --- a/packages/steward/README.md +++ b/packages/steward/README.md @@ -1,4 +1,4 @@ -# @sentinel/steward +# @agentic-sentinel/steward `sentinel-steward`: the Sentinel namespace-claim steward — an authenticated operational service for exact-apex DNS TXT claim challenges, three-tier @@ -10,7 +10,7 @@ retraction-corpus releases that Sentinel proxies consume offline. > without notice. Not production-ready. ```bash -npm install -g @sentinel/steward@alpha +npm install -g @agentic-sentinel/steward@alpha ``` All four variables are required: diff --git a/packages/steward/package.json b/packages/steward/package.json index 0234a0f..f1a6626 100644 --- a/packages/steward/package.json +++ b/packages/steward/package.json @@ -1,5 +1,5 @@ { - "name": "@sentinel/steward", + "name": "@agentic-sentinel/steward", "version": "0.1.0-alpha.1", "description": "Sentinel namespace-claim steward: DNS TXT claim verification, renewal/freeze lifecycle, timelocked transfers, and Ed25519-signed claim/retraction corpus releases.", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "npm-registry" ], "dependencies": { - "@sentinel/core": "0.1.0-alpha.1", + "@agentic-sentinel/core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, diff --git a/packages/steward/src/server.ts b/packages/steward/src/server.ts index 0cf2e62..994dd45 100644 --- a/packages/steward/src/server.ts +++ b/packages/steward/src/server.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import express, { type Request, type Response } from "express"; import { rateLimit } from "express-rate-limit"; import { ClaimSteward, type ClaimApplicationInput, type TxtResolver } from "./steward.js"; -import type { RetractionAdvisory } from "@sentinel/core"; +import type { RetractionAdvisory } from "@agentic-sentinel/core"; export interface StewardServerOptions { steward: ClaimSteward; diff --git a/packages/steward/src/steward.ts b/packages/steward/src/steward.ts index 7e79142..9d8d97e 100644 --- a/packages/steward/src/steward.ts +++ b/packages/steward/src/steward.ts @@ -17,7 +17,7 @@ import { signRetractionCorpus, type RetractionAdvisory, type RetractionCorpus, -} from "@sentinel/core"; +} from "@agentic-sentinel/core"; export type GrandfatherTier = 1 | 2 | 3; export type TxtResolver = (domain: string) => Promise; diff --git a/packages/steward/test/steward.test.ts b/packages/steward/test/steward.test.ts index 0f3f727..f2c6b71 100644 --- a/packages/steward/test/steward.test.ts +++ b/packages/steward/test/steward.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { basename, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, parseClaimCorpus, verifyClaimCorpusBytes, parseRetractionCorpus, verifyRetractionCorpusBytes } from "@sentinel/core"; +import { generateKeypair, parseClaimCorpus, verifyClaimCorpusBytes, parseRetractionCorpus, verifyRetractionCorpusBytes } from "@agentic-sentinel/core"; import { ClaimSteward, corroboratesClaimDomain, signTransferRequest, type UpstreamClaimLookup } from "../src/steward.js"; import { createStewardServer } from "../src/server.js"; diff --git a/scripts/benchmark-publish.ts b/scripts/benchmark-publish.ts index 679a1b7..06bc83e 100644 --- a/scripts/benchmark-publish.ts +++ b/scripts/benchmark-publish.ts @@ -7,7 +7,7 @@ import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; import { fileURLToPath } from "node:url"; import { c as createTar } from "tar"; -import { DEFAULT_POLICY, integrityOf, type EnterprisePolicy } from "@sentinel/core"; +import { DEFAULT_POLICY, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; import { createServer } from "../packages/proxy/src/server.js"; import { AuditStore } from "../packages/proxy/src/store.js"; import { ApprovalStore } from "../packages/proxy/src/approvals.js"; diff --git a/scripts/compat-clients.ts b/scripts/compat-clients.ts index ac37232..5f0ed67 100644 --- a/scripts/compat-clients.ts +++ b/scripts/compat-clients.ts @@ -6,7 +6,7 @@ import type { AddressInfo } from "node:net"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { promisify } from "node:util"; -import { DEFAULT_POLICY, integrityOf, runAudit } from "@sentinel/core"; +import { DEFAULT_POLICY, integrityOf, runAudit } from "@agentic-sentinel/core"; import { createServer } from "../packages/proxy/src/server.js"; import { AuditStore } from "../packages/proxy/src/store.js"; import { ApprovalStore } from "../packages/proxy/src/approvals.js"; diff --git a/scripts/demo.ts b/scripts/demo.ts index ac0bff2..5c121ff 100644 --- a/scripts/demo.ts +++ b/scripts/demo.ts @@ -16,7 +16,7 @@ import { ApprovalRequestStore } from "../packages/proxy/src/approval-requests.js import { LocalFixtureUpstream } from "../packages/proxy/src/upstream.js"; import { formatReport } from "../packages/cli/src/format.js"; import type { AuditReport } from "../packages/core/src/index.js"; -import { DEFAULT_POLICY } from "@sentinel/core"; +import { DEFAULT_POLICY } from "@agentic-sentinel/core"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index d57fd4f..0c6de9e 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -8,7 +8,7 @@ // - the proxy boots, serves the dashboard, and shuts down cleanly // - the MCP server answers an initialize handshake // - the steward fail-closes on missing config and boots with full config -// - internal @sentinel/* dependencies resolve from the packed tarballs only +// - internal @agentic-sentinel/* dependencies resolve from the packed tarballs only // // Requires network access (third-party deps install from the public registry). // Usage: npx tsx scripts/release-smoke.ts [--json ] [--pack-dest

] @@ -103,7 +103,7 @@ for (const ws of WORKSPACES) { const info = (JSON.parse(json) as { filename: string; size: number; entryCount: number; unpackedSize: number }[])[0]; const file = join(packDir, info.filename); const sha256 = createHash("sha256").update(readFileSync(file)).digest("hex"); - results.tarballs.push({ name: `@sentinel/${ws}`, file: info.filename, bytes: info.size, sha256, files: info.entryCount, unpacked: info.unpackedSize }); + results.tarballs.push({ name: `@agentic-sentinel/${ws}`, file: info.filename, bytes: info.size, sha256, files: info.entryCount, unpacked: info.unpackedSize }); console.log(` ${info.filename} ${info.size} B ${info.entryCount} files sha256:${sha256.slice(0, 16)}…`); } @@ -112,22 +112,22 @@ for (const ws of WORKSPACES) { // --------------------------------------------------------------------------- const proj = mkdtempSync(join(tmpdir(), "sentinel-smoke-")); console.log(`\n[2/5] fresh install into ${proj}`); -const fileDep = (ws: string) => `file:${join(packDir, results.tarballs.find((t) => t.name === `@sentinel/${ws}`)!.file)}`; +const fileDep = (ws: string) => `file:${join(packDir, results.tarballs.find((t) => t.name === `@agentic-sentinel/${ws}`)!.file)}`; const pkgJson = { name: "sentinel-release-smoke", private: true, version: "0.0.0", type: "module", - dependencies: Object.fromEntries(WORKSPACES.map((ws) => [`@sentinel/${ws}`, fileDep(ws)])), + dependencies: Object.fromEntries(WORKSPACES.map((ws) => [`@agentic-sentinel/${ws}`, fileDep(ws)])), // Internal deps are pinned to the (unpublished) exact prerelease version, so // transitive resolution must be forced to the local tarballs. - overrides: { "@sentinel/core": fileDep("core"), "@sentinel/proxy": fileDep("proxy"), "@sentinel/sandbox": fileDep("sandbox") }, + overrides: { "@agentic-sentinel/core": fileDep("core"), "@agentic-sentinel/proxy": fileDep("proxy"), "@agentic-sentinel/sandbox": fileDep("sandbox") }, }; writeFileSync(join(proj, "package.json"), JSON.stringify(pkgJson, null, 2)); run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], { cwd: proj }); console.log(" installed"); check("internal deps resolved from tarballs (not registry)", () => { const lock = JSON.parse(readFileSync(join(proj, "package-lock.json"), "utf8")) as { packages: Record }; - const bad = Object.entries(lock.packages).filter(([k, v]) => k.includes("@sentinel/") && v.resolved && !v.resolved.startsWith("file:")); + const bad = Object.entries(lock.packages).filter(([k, v]) => k.includes("@agentic-sentinel/") && v.resolved && !v.resolved.startsWith("file:")); if (bad.length) throw new Error(`registry-resolved: ${bad.map(([k]) => k).join(", ")}`); - return "all @sentinel/* resolved file:"; + return "all @agentic-sentinel/* resolved file:"; }); // --------------------------------------------------------------------------- @@ -135,22 +135,22 @@ check("internal deps resolved from tarballs (not registry)", () => { // --------------------------------------------------------------------------- console.log(`\n[3/5] imports + types`); for (const ws of WORKSPACES) { - check(`import @sentinel/${ws}`, () => { - run(process.execPath, ["-e", `import("@sentinel/${ws}").then((m)=>{ if(!m || typeof m !== "object") throw new Error("empty module") })`], { cwd: proj }); + check(`import @agentic-sentinel/${ws}`, () => { + run(process.execPath, ["-e", `import("@agentic-sentinel/${ws}").then((m)=>{ if(!m || typeof m !== "object") throw new Error("empty module") })`], { cwd: proj }); return ""; }); } check("ENGINE_VERSION matches release", () => { - const v = run(process.execPath, ["-e", `import("@sentinel/core").then((m)=>console.log(m.ENGINE_VERSION))`], { cwd: proj }).trim(); + const v = run(process.execPath, ["-e", `import("@agentic-sentinel/core").then((m)=>console.log(m.ENGINE_VERSION))`], { cwd: proj }).trim(); if (v !== VERSION) throw new Error(`ENGINE_VERSION=${v}, expected ${VERSION}`); return v; }); check("type declarations resolve (tsc --noEmit, NodeNext)", () => { run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error", "-D", "typescript@^6"], { cwd: proj }); writeFileSync(join(proj, "typecheck.ts"), [ - `import { runAudit, score, DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@sentinel/core";`, - `import { createServer, NpmUpstream, type Upstream } from "@sentinel/proxy";`, - `import { createSandbox, scrubEnv } from "@sentinel/sandbox";`, + `import { runAudit, score, DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core";`, + `import { createServer, NpmUpstream, type Upstream } from "@agentic-sentinel/proxy";`, + `import { createSandbox, scrubEnv } from "@agentic-sentinel/sandbox";`, `const p: EnterprisePolicy = DEFAULT_POLICY;`, `void p; void runAudit; void score; void createServer; void createSandbox; void scrubEnv;`, `const u: Upstream | null = null; void u;`, diff --git a/sentinel-threat-model.md b/sentinel-threat-model.md index 92fab80..2f5f3cd 100644 --- a/sentinel-threat-model.md +++ b/sentinel-threat-model.md @@ -291,13 +291,13 @@ and stays filesystem+network confined as before. The Phase 29 `/dev/null` carve-out is unchanged (Landlock is allow-list-only and can't deny a literal under an allowed dir). `native` is advisory-only on both platforms by decision. A spawned child inherits the filesystem/network confinement on both platforms. -**Distribution note (ADR-0052):** the published `@sentinel/sandbox` npm package +**Distribution note (ADR-0052):** the published `@agentic-sentinel/sandbox` npm package ships the Landlock helper as *source only* — no prebuilt binary (it would be architecture-specific presented as portable) and no install-time compilation (a posture violation for a tool that guards against lifecycle scripts). A fresh npm install therefore runs the advisory exec floor on Linux, announced by a one-time notice, until the operator explicitly compiles the helper -(`node node_modules/@sentinel/sandbox/scripts/build-native.mjs`); monorepo +(`node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs`); monorepo builds are unchanged. A cross-platform exec floor now exists (macOS Seatbelt, Linux Landlock where available); [issue #8](https://github.com/git-agentic/pkg-registry/issues/8) From bf1e0eca673aadc76b307e0c8179c890b8fccc9f Mon Sep 17 00:00:00 2001 From: Toni Bergholm Date: Tue, 14 Jul 2026 07:36:39 +0300 Subject: [PATCH 3/3] =?UTF-8?q?Rename=20npm=20packages:=20@agentic-sentine?= =?UTF-8?q?l/*=20=E2=86=92=20@git-agentic/sentinel-*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The npm org is git-agentic (matching the GitHub org), so the packages publish as @git-agentic/sentinel-{core,proxy,sandbox,cli,mcp,steward, action} — the sentinel- prefix keeps the product identity inside the shared org scope. Bin names unchanged. Historical docs (docs/archive/, ADRs 0001-0051) keep their original spelling. Lockfile regenerated; full suite green (997/994/3 skipped) and pack-smoke 19/19 under the final names. Claude-Session: https://claude.ai/code/session_01LjqCaCwPby6EGi4RmBVtEW --- .github/workflows/release.yml | 32 +++---- ARCHITECTURE.md | 30 +++---- CLAUDE.md | 18 ++-- README.md | 14 +-- SECURITY.md | 2 +- .../0052-native-helper-release-packaging.md | 8 +- docs/adr/README.md | 2 +- docs/product/registry-roadmap.md | 2 +- docs/release-process.md | 16 ++-- docs/releases/v0.1.0-alpha.1.md | 30 +++---- ...6-07-12-native-payload-loader-detection.md | 12 +-- ...-native-payload-loader-detection-design.md | 2 +- package-lock.json | 86 +++++++++---------- packages/action/README.md | 4 +- packages/action/package.json | 6 +- packages/action/src/index.ts | 6 +- packages/action/src/report.ts | 4 +- packages/action/src/run.ts | 4 +- packages/action/test/report.test.ts | 2 +- packages/action/test/run-e2e.test.ts | 2 +- packages/cli/README.md | 8 +- packages/cli/package.json | 6 +- packages/cli/src/enforce.ts | 2 +- packages/cli/src/format.ts | 2 +- packages/cli/src/index.ts | 4 +- packages/cli/src/script-shell.ts | 6 +- packages/cli/test/attest-cli-e2e.test.ts | 2 +- packages/cli/test/audit-tree-cli-e2e.test.ts | 2 +- packages/cli/test/explain-cli-e2e.test.ts | 2 +- packages/cli/test/format-tree.test.ts | 2 +- .../cli/test/policy-authoring-cli-e2e.test.ts | 4 +- packages/cli/test/policy.test.ts | 2 +- packages/cli/test/run-scripts.test.ts | 2 +- .../cli/test/stats-history-cli-e2e.test.ts | 4 +- packages/core/README.md | 6 +- packages/core/package.json | 2 +- packages/core/src/index.ts | 2 +- packages/core/test/package-contents.test.ts | 6 +- packages/mcp/README.md | 4 +- packages/mcp/package.json | 4 +- packages/mcp/src/client.ts | 2 +- packages/mcp/src/format.ts | 2 +- packages/mcp/src/tools.ts | 2 +- packages/mcp/test/client-auth.test.ts | 2 +- packages/mcp/test/client.test.ts | 2 +- packages/mcp/test/server-e2e.test.ts | 2 +- packages/mcp/test/tools.test.ts | 2 +- packages/proxy/README.md | 4 +- packages/proxy/package.json | 4 +- packages/proxy/src/approval-requests.ts | 2 +- packages/proxy/src/approvals.ts | 2 +- packages/proxy/src/authz.ts | 2 +- packages/proxy/src/cooldown.ts | 2 +- packages/proxy/src/history-db.ts | 2 +- packages/proxy/src/index.ts | 2 +- packages/proxy/src/private-store.ts | 4 +- packages/proxy/src/reconcile.ts | 2 +- packages/proxy/src/registry-mode.ts | 2 +- packages/proxy/src/resolution.ts | 6 +- packages/proxy/src/server.ts | 2 +- packages/proxy/src/store.ts | 2 +- packages/proxy/src/upstream.ts | 2 +- .../proxy/test/approval-requests-e2e.test.ts | 2 +- packages/proxy/test/audit-tree-e2e.test.ts | 2 +- .../test/audit-tree-integrity-e2e.test.ts | 2 +- .../proxy/test/audit-tree-limits-e2e.test.ts | 2 +- packages/proxy/test/auth-config.test.ts | 2 +- packages/proxy/test/authz-e2e.test.ts | 2 +- packages/proxy/test/authz-unit.test.ts | 2 +- .../proxy/test/claim-corpus-startup.test.ts | 2 +- .../proxy/test/claim-lifecycle-e2e.test.ts | 2 +- packages/proxy/test/coalesce-e2e.test.ts | 2 +- packages/proxy/test/compatibility-e2e.test.ts | 2 +- packages/proxy/test/cooldown-e2e.test.ts | 2 +- packages/proxy/test/cooldown.test.ts | 2 +- packages/proxy/test/enforce-e2e.test.ts | 2 +- packages/proxy/test/explain-e2e.test.ts | 2 +- .../proxy/test/history-db-queries.test.ts | 2 +- packages/proxy/test/history-db.test.ts | 2 +- .../proxy/test/history-endpoints-e2e.test.ts | 4 +- .../proxy/test/history-writethrough.test.ts | 2 +- .../proxy/test/known-advisory-e2e.test.ts | 2 +- .../test/known-vulnerability-e2e.test.ts | 2 +- .../proxy/test/payload-loader-e2e.test.ts | 2 +- .../proxy/test/policy-preview-e2e.test.ts | 4 +- packages/proxy/test/policy-startup.test.ts | 2 +- packages/proxy/test/private-serve.test.ts | 2 +- packages/proxy/test/private-store.test.ts | 2 +- packages/proxy/test/provenance-verify.test.ts | 2 +- packages/proxy/test/proxy.test.ts | 2 +- .../proxy/test/public-base-url-e2e.test.ts | 2 +- packages/proxy/test/publish.test.ts | 2 +- packages/proxy/test/rate-limit-e2e.test.ts | 2 +- packages/proxy/test/reconcile.test.ts | 2 +- .../proxy/test/registry-migration.test.ts | 2 +- .../proxy/test/registry-mode-startup.test.ts | 2 +- .../proxy/test/release-anomaly-e2e.test.ts | 2 +- packages/proxy/test/resolution.test.ts | 2 +- packages/proxy/test/retraction-e2e.test.ts | 2 +- packages/proxy/test/signature-verify.test.ts | 2 +- packages/proxy/test/tree.test.ts | 2 +- packages/proxy/test/typosquat-e2e.test.ts | 2 +- .../proxy/test/violation-enforce-e2e.test.ts | 2 +- packages/proxy/test/violations-e2e.test.ts | 2 +- .../proxy/test/violations-startup.test.ts | 2 +- packages/sandbox/README.md | 6 +- packages/sandbox/package.json | 4 +- packages/sandbox/src/bubblewrap.ts | 2 +- packages/sandbox/src/bwrap.ts | 2 +- packages/sandbox/src/deny-set.ts | 2 +- packages/sandbox/src/env.ts | 2 +- packages/sandbox/src/profile.ts | 2 +- packages/sandbox/src/runner.ts | 2 +- packages/sandbox/src/seatbelt.ts | 2 +- packages/sandbox/src/types.ts | 2 +- packages/sandbox/test/bubblewrap.test.ts | 4 +- packages/sandbox/test/bwrap.test.ts | 2 +- packages/sandbox/test/deny-set.test.ts | 2 +- packages/sandbox/test/env.test.ts | 2 +- packages/sandbox/test/profile.test.ts | 2 +- packages/sandbox/test/runner.test.ts | 2 +- packages/sandbox/test/seatbelt.test.ts | 2 +- packages/steward/README.md | 4 +- packages/steward/package.json | 4 +- packages/steward/src/server.ts | 2 +- packages/steward/src/steward.ts | 2 +- packages/steward/test/steward.test.ts | 2 +- scripts/benchmark-publish.ts | 2 +- scripts/compat-clients.ts | 2 +- scripts/demo.ts | 2 +- scripts/release-smoke.ts | 26 +++--- sentinel-threat-model.md | 4 +- 132 files changed, 295 insertions(+), 295 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ee3586..abe3ddc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,8 +170,8 @@ jobs: set -euo pipefail VERSION="${RELEASE_TAG#v}" for p in core proxy sandbox mcp steward cli action; do - if npm view "@agentic-sentinel/$p@$VERSION" version >/dev/null 2>&1; then - echo "::error::@agentic-sentinel/$p@$VERSION already exists on the registry — refusing to continue"; exit 1 + if npm view "@git-agentic/sentinel-$p@$VERSION" version >/dev/null 2>&1; then + echo "::error::@git-agentic/sentinel-$p@$VERSION already exists on the registry — refusing to continue"; exit 1 fi done echo "no target version exists — safe to publish" @@ -184,13 +184,13 @@ jobs: VERSION="${RELEASE_TAG#v}" published="" for p in core proxy sandbox mcp steward cli action; do - t="release-artifacts/agentic-sentinel-$p-$VERSION.tgz" - echo "publishing @agentic-sentinel/$p@$VERSION" + t="release-artifacts/git-agentic-sentinel-$p-$VERSION.tgz" + echo "publishing @git-agentic/sentinel-$p@$VERSION" if ! npm publish "$t" --access public --tag alpha --provenance; then - echo "::error::publish of @agentic-sentinel/$p failed. Already published (immutable): ${published:-none}. Do NOT unpublish; fix forward."; exit 1 + echo "::error::publish of @git-agentic/sentinel-$p failed. Already published (immutable): ${published:-none}. Do NOT unpublish; fix forward."; exit 1 fi - published="$published @agentic-sentinel/$p" - echo "- @agentic-sentinel/$p@$VERSION published" >> "$GITHUB_STEP_SUMMARY" + published="$published @git-agentic/sentinel-$p" + echo "- @git-agentic/sentinel-$p@$VERSION published" >> "$GITHUB_STEP_SUMMARY" done - name: Verify every published package via npm view run: | @@ -198,14 +198,14 @@ jobs: VERSION="${RELEASE_TAG#v}" for p in core proxy sandbox mcp steward cli action; do for i in 1 2 3 4 5; do - got="$(npm view "@agentic-sentinel/$p@$VERSION" version 2>/dev/null || true)" + got="$(npm view "@git-agentic/sentinel-$p@$VERSION" version 2>/dev/null || true)" [ "$got" = "$VERSION" ] && break sleep 15 done - [ "$got" = "$VERSION" ] || { echo "::error::@agentic-sentinel/$p@$VERSION not visible after publish"; exit 1; } - tag_alpha="$(npm view "@agentic-sentinel/$p" dist-tags.alpha)" - [ "$tag_alpha" = "$VERSION" ] || { echo "::error::@agentic-sentinel/$p dist-tag alpha is $tag_alpha, expected $VERSION"; exit 1; } - echo "@agentic-sentinel/$p@$VERSION visible, dist-tag alpha OK" + [ "$got" = "$VERSION" ] || { echo "::error::@git-agentic/sentinel-$p@$VERSION not visible after publish"; exit 1; } + tag_alpha="$(npm view "@git-agentic/sentinel-$p" dist-tags.alpha)" + [ "$tag_alpha" = "$VERSION" ] || { echo "::error::@git-agentic/sentinel-$p dist-tag alpha is $tag_alpha, expected $VERSION"; exit 1; } + echo "@git-agentic/sentinel-$p@$VERSION visible, dist-tag alpha OK" done - name: Install the published packages from the public registry in a clean project run: | @@ -217,13 +217,13 @@ jobs: # retry: registry propagation can lag the view endpoint for i in 1 2 3 4 5; do npm install --no-audit --no-fund \ - "@agentic-sentinel/core@$VERSION" "@agentic-sentinel/proxy@$VERSION" "@agentic-sentinel/sandbox@$VERSION" \ - "@agentic-sentinel/mcp@$VERSION" "@agentic-sentinel/steward@$VERSION" "@agentic-sentinel/cli@$VERSION" \ - "@agentic-sentinel/action@$VERSION" && break + "@git-agentic/sentinel-core@$VERSION" "@git-agentic/sentinel-proxy@$VERSION" "@git-agentic/sentinel-sandbox@$VERSION" \ + "@git-agentic/sentinel-mcp@$VERSION" "@git-agentic/sentinel-steward@$VERSION" "@git-agentic/sentinel-cli@$VERSION" \ + "@git-agentic/sentinel-action@$VERSION" && break sleep 20 done ./node_modules/.bin/sentinel --version | grep -qx "$VERSION" - node -e "import('@agentic-sentinel/core').then(m=>{if(m.ENGINE_VERSION!=='$VERSION')process.exit(1)})" + node -e "import('@git-agentic/sentinel-core').then(m=>{if(m.ENGINE_VERSION!=='$VERSION')process.exit(1)})" echo "clean-project registry install OK" - name: Create the GitHub prerelease (only after npm verification) env: diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ec60851..21f6ad5 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -61,17 +61,17 @@ package is installed and approved is out of scope. Seven packages (npm workspaces monorepo; key registry packages below): -- **`@agentic-sentinel/core`** — the audit engine. Pure, dependency-light, deterministic. +- **`@git-agentic/sentinel-core`** — the audit engine. Pure, dependency-light, deterministic. Tarball extraction, the rules, scoring, the data model, and the LLM adapter interface. No HTTP, no Express — so it is trivially unit-testable and reusable (CLI, proxy, CI all import it). -- **`@agentic-sentinel/proxy`** — Express server implementing the npm registry HTTP API +- **`@git-agentic/sentinel-proxy`** — Express server implementing the npm registry HTTP API surface we need (`GET /:pkg`, `GET /:pkg/-/:tarball`). Pluggable upstream (`NpmUpstream` for the real registry, `LocalFixtureUpstream` for hermetic tests). Owns the verdict cache + audit store and serves the dashboard. -- **`@agentic-sentinel/cli`** — `sentinel audit ` (one-shot) and `sentinel install …` +- **`@git-agentic/sentinel-cli`** — `sentinel audit ` (one-shot) and `sentinel install …` (sets `registry` to the proxy and runs npm, showing the pre-install verdict). -- **`@agentic-sentinel/steward`** — authenticated DNS-claim issuance, renewal/freeze, +- **`@git-agentic/sentinel-steward`** — authenticated DNS-claim issuance, renewal/freeze, timelocked ownership changes, and signed offline claim-corpus releases. It is operationally separate from the proxy's offline resolution path. - **dashboard** — a single self-contained HTML page served by the proxy at `/`. @@ -182,7 +182,7 @@ the policy hash. Frozen/disputed claims remain native for reads but reject write trusted-publisher enrollments require a matching offline-verified Sigstore SLSA identity. Stored native versions snapshot the claim namespace, domain, and claimant key at publication, so an ownership change cannot re-attribute history. -`@agentic-sentinel/steward` performs exact-apex DNS challenges, derives grandfather tiers +`@git-agentic/sentinel-steward` performs exact-apex DNS challenges, derives grandfather tiers from steward-fetched upstream evidence, verifies claimant-key transfer signatures, applies renewal/domain-change freezes, and atomically publishes versioned directories after 30-day announced changes (ADR-0046). Mandatory @@ -241,7 +241,7 @@ never stored. ### 3.6 Sandbox enforcement (Phases 3–5, ADR-0011/0016/0017/0018) -`@agentic-sentinel/sandbox` turns an *approved* capability set into *enforced* runtime +`@git-agentic/sentinel-sandbox` turns an *approved* capability set into *enforced* runtime least-privilege on macOS and Linux: `generateProfile(approved, {homeDir})` emits an allow-default + deny-sensitive Seatbelt (SBPL) profile, each deny relaxed by an approved capability; the `SeatbeltSandbox` runs each lifecycle script under it via `sandbox-exec` (failing closed @@ -276,7 +276,7 @@ any negative falls back to the Phase 29 advisory floor with a one-time notice, so a Landlock-less or no-`cc` host never regresses. `computeDenySet` gains a `linux-landlock` `execFloorMode` and `classifyViolation` confirms a floor-outside exec denial as `exec-floor-deny`. The *published* -`@agentic-sentinel/sandbox` package ships the helper as source only +`@git-agentic/sentinel-sandbox` package ships the helper as source only (`native/landlock-exec.c` + `scripts/build-native.mjs`) — never a prebuilt binary and never a `postinstall` compile; a fresh npm install runs this same advisory fallback until the operator explicitly compiles the helper @@ -358,7 +358,7 @@ by sniffing for `__metadata:`), and `pnpm-lock.yaml` (YAML across lockfile versi into the same deduped, sorted `{name, version, integrity?}` `Coordinate[]` regardless of format (skipping the root entry and `link:`/`file:` deps). Berry checksums are not SRI-shaped, so berry-parsed coordinates carry no `integrity`. The `yaml` package -(`^2.9.0`) backing the pnpm/berry parsers is a dependency of `@agentic-sentinel/core` only. The CLI +(`^2.9.0`) backing the pnpm/berry parsers is a dependency of `@git-agentic/sentinel-core` only. The CLI POSTs the coordinates (plus an optional `failOnError` flag) to `POST /-/audit-tree`. The proxy fans out with bounded concurrency over the same integrity-cached `auditVersion()` path used by the tarball route, then rolls the per-package verdicts into a worst-case-wins @@ -762,7 +762,7 @@ deferred. Phases 1–16 gate installs and lockfiles, but only when a human or CI job already knows to run `sentinel audit-tree` against a proxy someone started. Phase 17 adds a self-contained on-ramp into GitHub PRs: a new -**`@agentic-sentinel/action`** workspace (`packages/action`, bin `sentinel-ci`) that +**`@git-agentic/sentinel-action`** workspace (`packages/action`, bin `sentinel-ci`) that needs nothing already running. - **`runCi(opts)`** (`packages/action/src/run.ts`) self-boots @@ -797,9 +797,9 @@ needs nothing already running. marker instead of always appending a new one. `.github/workflows/sentinel-example.yml` shows minimal usage. - **The proxy entrypoint-guard root fix.** `packages/proxy/src/index.ts`'s - `main()` is now guarded the same way `@agentic-sentinel/mcp`'s bin already is + `main()` is now guarded the same way `@git-agentic/sentinel-mcp`'s bin already is (`isEntrypoint()` comparing `import.meta.url` to the resolved - `process.argv[1]`) — importing `@agentic-sentinel/proxy` for its exports no + `process.argv[1]`) — importing `@git-agentic/sentinel-proxy` for its exports no longer boots a listening server as a side effect. This is what makes `runCi`'s self-boot import-safe. @@ -1035,7 +1035,7 @@ releases, deferring version-range CVE matching. Phase 22 closes that gap: SCA exposure across `audit-tree`'s whole dependency graph. - A `known-vulnerability` entry in `REMEDIATIONS` (§3.17/ADR-0031) plus a `vulnerability` `CATEGORY_FALLBACK` entry. -- Adds `semver` (^7.x) as a `@agentic-sentinel/core` runtime dependency — the first +- Adds `semver` (^7.x) as a `@git-agentic/sentinel-core` runtime dependency — the first real semver-range parser in the corpus/rule family. Faithful severity is a deliberate gating stance (diverges from `npm audit`'s @@ -1342,7 +1342,7 @@ which explicitly extends [ADR-0041](./docs/adr/0041-review-hardening.md). --- -## 4. The audit engine (`@agentic-sentinel/core`) +## 4. The audit engine (`@git-agentic/sentinel-core`) Deterministic heuristic core + a pluggable LLM adapter. The score is produced **entirely by the heuristic rules** so it is reproducible and testable; the LLM @@ -1595,8 +1595,8 @@ Five integration modes, all non-invasive: see; a `ProxyClient` failure (unreachable proxy, non-OK response) throws `ProxyError` rather than ever fabricating a verdict, and the MCP layer performs zero scoring of its own (invariant #1 untouched). `parseLockfile` - (used by `sentinel_audit_tree`) moved from `@agentic-sentinel/cli` to - `@agentic-sentinel/core` this phase so both packages can share it without `mcp` + (used by `sentinel_audit_tree`) moved from `@git-agentic/sentinel-cli` to + `@git-agentic/sentinel-core` this phase so both packages can share it without `mcp` tripping `cli`'s own entrypoint guard. The cleanest hook is registry redirection (`.npmrc` `registry=` or `--registry`) diff --git a/CLAUDE.md b/CLAUDE.md index fb7acd7..e511686 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,7 +29,7 @@ ADR-0045–0048 and threat-model §6. ### Current state by subsystem -**Scoring & rules (`@agentic-sentinel/core`)** — 10 registered pure rules +**Scoring & rules (`@git-agentic/sentinel-core`)** — 10 registered pure rules (`packages/core/src/rules/index.ts`): install-scripts, secret-exfil, network-egress, obfuscation, provenance (ADR-0021/0022), typosquat (ADR-0026), release-anomaly (ADR-0029), known-advisory (ADR-0034), known-vulnerability @@ -52,7 +52,7 @@ at audit time. Also here: multi-format lockfile parsing (npm/yarn/pnpm) + Cyclon 1.6 SBOM export (ADR-0027), `remediate()` advisory fixes (ADR-0031), in-toto/DSSE signed audit attestations (ADR-0032), `lintPolicy` (ADR-0033). -**Proxy (`@agentic-sentinel/proxy`)** — sync inline gate over bytes in memory, cached by +**Proxy (`@git-agentic/sentinel-proxy`)** — sync inline gate over bytes in memory, cached by `dist.integrity`; transparent packument passthrough rewriting only `dist.tarball`. Private-namespace packages are served only from the private store, fail-closed (ADR-0010/0015). `POST /-/audit-tree` whole-lockfile gate with dedupe + 413 cap @@ -75,7 +75,7 @@ configured public base URL off loopback — 421 otherwise (ADR-0036). Byte caps, request coalescing, and an opt-in token-bucket rate limiter round out resource robustness; install-gate paths are never rate-limited (ADR-0037). `packages/proxy/src/index.ts`'s `main()` is entrypoint-guarded — importing -`@agentic-sentinel/proxy` must never boot a server as a side effect (ADR-0030). +`@git-agentic/sentinel-proxy` must never boot a server as a side effect (ADR-0030). Phase 30 generalizes private publishing into an authoritative native write path: pure `source(name, signedPolicy, claimCorpus)` selects policy-private → verified-claim → public-mirror without version merging; native names never fall @@ -109,7 +109,7 @@ it runs each client's exposed mutation commands (Berry has no unpublish; bun has neither dist-tag nor unpublish), while the wire suite covers the complete shared route contract. -**Claim steward (`@agentic-sentinel/steward`)** — authenticated operational service for +**Claim steward (`@git-agentic/sentinel-steward`)** — authenticated operational service for exact-apex DNS TXT challenges, steward-fetched three-tier grandfathering, claimant-key-signed transfers, 12-month renewal and freeze, 30-day announced Tier-2 grants/transfers/dispute rulings, durable atomic state, and atomic @@ -122,7 +122,7 @@ history. The steward control plane and proxy publish route have mandatory per-source rate-limit backstops; release directory names are generated independently of request data. -**Sandbox (`@agentic-sentinel/sandbox`)** — `createSandbox()` selects Seatbelt (darwin) +**Sandbox (`@git-agentic/sentinel-sandbox`)** — `createSandbox()` selects Seatbelt (darwin) or bubblewrap (linux); one approved-capability model, fail-closed contract (ADR-0016/0018). Posture is **deny-by-default**: writes closed except a fixed `writeAllowFloor` + Grants, `$HOME` reads closed except `readAllowList` @@ -146,7 +146,7 @@ outside `exec` remain uncontained (ADR-0051). **CLI / CI / MCP** — `sentinel` CLI: `audit-tree`, `explain`, `stats`/`history`, `policy init|validate|preview|keygen|sign|verify`, `attest-keygen`/`attest`/ -`verify-attestation`, `run-scripts`, `install --enforce`, `exec`. `@agentic-sentinel/action` +`verify-attestation`, `run-scripts`, `install --enforce`, `exec`. `@git-agentic/sentinel-action` (bin `sentinel-ci`) self-boots the proxy in-process for CI, writes SBOM + GitHub-native outputs, idempotent PR comment (ADR-0030). `sentinel-mcp` exposes read tools plus a single write tool that only ever *requests* approval — a human @@ -226,8 +226,8 @@ enforcement is tested with benign probe packages. Node + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`, `mcp`, `action`, `steward` — `action` is the GitHub Action, bin `sentinel-ci`), Express 5, `tar` 7, -`commander` 15, `yaml` 2 (`@agentic-sentinel/core` only — pnpm/yarn-berry lockfile -parsing), `semver` 7 (`@agentic-sentinel/core` vulnerability range matching), tests on +`commander` 15, `yaml` 2 (`@git-agentic/sentinel-core` only — pnpm/yarn-berry lockfile +parsing), `semver` 7 (`@git-agentic/sentinel-core` vulnerability range matching), tests on `node:test` + `tsx`. Developed against **Node 24 (Active LTS)**; Node 22 (Maintenance LTS) also supported — `engines.node` is `>=22`. Pin to current latest; don't downgrade majors without a reason. `node:sqlite` is a built-in, @@ -236,7 +236,7 @@ Node 22 needs `--experimental-sqlite`). The Landlock helper (`packages/sandbox/native/landlock-exec.c`) is compiled by `npm run build` (`build-native.mjs`, Linux + `cc` only, no-op elsewhere) — **never** a `postinstall` hook or lazy runtime compile; both would be posture violations for -a tool that guards against exactly that. The *published* `@agentic-sentinel/sandbox` +a tool that guards against exactly that. The *published* `@git-agentic/sentinel-sandbox` ships the helper as source only (no prebuilt binary in any tarball — enforced by `packages/core/test/package-contents.test.ts`); npm installs opt in via an explicit `node …/scripts/build-native.mjs` (ADR-0052). Releases version all diff --git a/README.md b/README.md index 05a7d67..a733e5f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ has not yet been hardened by production use, and APIs may change without notice. The complete phase-by-phase build log lives in [docs/adr/](./docs/adr/) (one ADR per phase). **Published as an alpha preview**: all seven packages ship as `0.1.0-alpha.1` under the `alpha` -dist-tag (`npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha`) — see +dist-tag (`npm install -g @git-agentic/sentinel-cli@alpha @git-agentic/sentinel-proxy@alpha`) — see the [release notes](./docs/releases/v0.1.0-alpha.1.md) and [release process](./docs/release-process.md); building from source (Quickstart below) remains fully supported. Threat model: @@ -697,7 +697,7 @@ There is no auto-approve or clear-quarantine tool, and none is planned — see ## GitHub Action (Phase 17) -`@agentic-sentinel/action` (bin `sentinel-ci`) is a self-contained on-ramp into pull +`@git-agentic/sentinel-action` (bin `sentinel-ci`) is a self-contained on-ramp into pull requests — it needs no separately-running proxy. `runCi` self-boots the proxy in-process against real npm, audits your lockfile through the same `/-/audit-tree` route the CLI uses, writes a CycloneDX SBOM, and posts the @@ -785,11 +785,11 @@ clear it without weakening detection. ``` packages/ - core/ @agentic-sentinel/core audit engine — rules, scoring, data model, LLM adapter (no I/O, fully unit-tested) - proxy/ @agentic-sentinel/proxy Express registry proxy, pluggable upstream, audit store, dashboard - cli/ @agentic-sentinel/cli pre-install verdicts + registry-redirected npm/npx - mcp/ @agentic-sentinel/mcp sentinel-mcp: stdio MCP server, thin client to the proxy (Phase 11) - action/ @agentic-sentinel/action sentinel-ci: self-boots the proxy for GitHub Actions (Phase 17) + core/ @git-agentic/sentinel-core audit engine — rules, scoring, data model, LLM adapter (no I/O, fully unit-tested) + proxy/ @git-agentic/sentinel-proxy Express registry proxy, pluggable upstream, audit store, dashboard + cli/ @git-agentic/sentinel-cli pre-install verdicts + registry-redirected npm/npx + mcp/ @git-agentic/sentinel-mcp sentinel-mcp: stdio MCP server, thin client to the proxy (Phase 11) + action/ @git-agentic/sentinel-action sentinel-ci: self-boots the proxy for GitHub Actions (Phase 17) fixtures/ benign + synthetic-malicious packages; make-fixtures.ts packs real .tgz tarballs scripts/ make-fixtures.ts, demo.ts ARCHITECTURE.md full design · CLAUDE.md working agreement for this repo diff --git a/SECURITY.md b/SECURITY.md index 29bd728..2549f98 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ sandbox for the npm ecosystem. We treat reports against it accordingly. ## Supported versions Sentinel is pre-1.0. Only the tip of `main` and the most recent published -prerelease (`@agentic-sentinel/*@alpha`, currently `0.1.0-alpha.1`) are supported; +prerelease (`@git-agentic/sentinel-*@alpha`, currently `0.1.0-alpha.1`) are supported; there are no maintained release branches. Prereleases are snapshots of `main` — fixes ship as the next prerelease, never as patches to an old one. diff --git a/docs/adr/0052-native-helper-release-packaging.md b/docs/adr/0052-native-helper-release-packaging.md index ae9afbc..a1780d1 100644 --- a/docs/adr/0052-native-helper-release-packaging.md +++ b/docs/adr/0052-native-helper-release-packaging.md @@ -37,7 +37,7 @@ exfil-tool carve-out unaffected. ## Decision -For `0.1.0-alpha.1`, `@agentic-sentinel/sandbox` ships the helper **as source only**, +For `0.1.0-alpha.1`, `@git-agentic/sentinel-sandbox` ships the helper **as source only**, with an explicit, operator-invoked build path and the documented advisory fallback: @@ -51,7 +51,7 @@ fallback: `scripts/build-native.mjs`. Both are first-party, reviewed files — the same from-source posture ADR-0044 chose over prebuilt distribution. 3. **Compilation is an explicit operator action, never a lifecycle script.** - `node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs` compiles the + `node node_modules/@git-agentic/sentinel-sandbox/scripts/build-native.mjs` compiles the helper in place (Linux + `cc` only; a no-op elsewhere). There is no `postinstall`, no lazy runtime compile, and no network fetch. The package README documents the command and the trade-off. @@ -71,7 +71,7 @@ fallback: ## Alternatives considered -- **Architecture-specific optional packages (`@agentic-sentinel/landlock-linux-x64`, +- **Architecture-specific optional packages (`@git-agentic/sentinel-landlock-linux-x64`, … via `optionalDependencies` + `os`/`cpu`, the esbuild/swc pattern).** The strongest end-state — prebuilt, reproducible, no toolchain requirement — and the likely post-alpha direction. Rejected *for the alpha*: it multiplies the @@ -87,7 +87,7 @@ fallback: x64 artifact silently presented as portable, unreproducible from the tarball, and a standing temptation for the release pipeline to become a binary-injection point. -- **Blocking publication of `@agentic-sentinel/sandbox` (and its dependents).** +- **Blocking publication of `@git-agentic/sentinel-sandbox` (and its dependents).** Unnecessary — ADR-0044's fallback is a designed, tested, honest degradation, not a silent weakening: the notice states the exact residual (a dropped binary can exec but stays filesystem+network confined), and the enforced diff --git a/docs/adr/README.md b/docs/adr/README.md index 548969c..78e47db 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -145,7 +145,7 @@ first shipped slice; Phases 31 and 32 complete claiming and retraction. | ADR | Title | Decision in one line | |-----|-------|----------------------| | [0051](./0051-sandboxed-exec.md) | Sandboxed `sentinel exec` | `Sandbox.runArgv` (no-shell, execFile-style) + `sentinel exec -- ` reuse the approved-capability model, scrubbed env, and violation telemetry to contain Sentinel-mediated command execution; scoped to explicit invocations only — raw `require()`/`npx` outside it stay uncontained, defense-in-depth behind the ADR-0049 registry gate | -| [0052](./0052-native-helper-release-packaging.md) | Landlock helper release packaging | The published `@agentic-sentinel/sandbox` ships the helper as source only (`native/landlock-exec.c` + `build-native.mjs`) — never a prebuilt binary, never a `postinstall` compile; fresh Linux installs run the documented advisory exec floor with a one-time notice until the operator explicitly compiles the helper; enforced by the package-contents test and a missing-helper CI test | +| [0052](./0052-native-helper-release-packaging.md) | Landlock helper release packaging | The published `@git-agentic/sentinel-sandbox` ships the helper as source only (`native/landlock-exec.c` + `build-native.mjs`) — never a prebuilt binary, never a `postinstall` compile; fresh Linux installs run the documented advisory exec floor with a one-time notice until the operator explicitly compiles the helper; enforced by the package-contents test and a missing-helper CI test | ## Conventions diff --git a/docs/product/registry-roadmap.md b/docs/product/registry-roadmap.md index d016d4f..cf10dfa 100644 --- a/docs/product/registry-roadmap.md +++ b/docs/product/registry-roadmap.md @@ -143,7 +143,7 @@ Evidence: `packages/core/test/claim-corpus.test.ts`, `packages/steward/test/steward.test.ts`. Applicant input cannot select a grandfather tier: the steward owns the upstream lookup, and voluntary transfers must verify against the current claim's Ed25519 key. The proxy remains an -offline consumer; the authenticated `@agentic-sentinel/steward` service owns DNS +offline consumer; the authenticated `@git-agentic/sentinel-steward` service owns DNS verification, durable renewal state, timelocked issuance changes, and signed release output. diff --git a/docs/release-process.md b/docs/release-process.md index 201595a..b30fd49 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -11,10 +11,10 @@ Seven workspaces publish under the `@sentinel` scope; the root `sentinel-registry` package is `private` and never publishes. Publication must follow the internal dependency graph: -1. `@agentic-sentinel/core` -2. `@agentic-sentinel/proxy`, `@agentic-sentinel/sandbox`, `@agentic-sentinel/mcp`, `@agentic-sentinel/steward` -3. `@agentic-sentinel/cli` (depends on core + sandbox) -4. `@agentic-sentinel/action` (depends on core + proxy) +1. `@git-agentic/sentinel-core` +2. `@git-agentic/sentinel-proxy`, `@git-agentic/sentinel-sandbox`, `@git-agentic/sentinel-mcp`, `@git-agentic/sentinel-steward` +3. `@git-agentic/sentinel-cli` (depends on core + sandbox) +4. `@git-agentic/sentinel-action` (depends on core + proxy) The release workflow publishes in exactly this order and stops at the first failure without unpublishing anything already released. @@ -27,7 +27,7 @@ failure without unpublishing anything already released. - All seven packages version in lockstep — one release version across the workspace, even for packages with no changes. Lockstep keeps the internal dependency pins trivially correct and the support matrix one-dimensional. -- Internal dependencies are pinned **exact** (`"@agentic-sentinel/core": "0.1.0-alpha.1"`, +- Internal dependencies are pinned **exact** (`"@git-agentic/sentinel-core": "0.1.0-alpha.1"`, no `^`/`~`, never `workspace:*` or `file:` in a published manifest). A prerelease must never float onto a different prerelease. - User-visible hardcoded versions move with the release: @@ -82,7 +82,7 @@ from a PR-triggered workflow. Prefer npm **trusted publishing** (GitHub Actions OIDC) over any long-lived token: configure the repo/workflow as a trusted publisher for each -`@agentic-sentinel/*` package on npmjs.com and leave `NPM_TOKEN` unset — npm ≥ 11.5 +`@git-agentic/sentinel-*` package on npmjs.com and leave `NPM_TOKEN` unset — npm ≥ 11.5 detects OIDC automatically and mints per-publish credentials. Until trusted publishing is configured (it may not be configurable before a package's first publish), use a **granular automation token scoped to the @sentinel @@ -108,10 +108,10 @@ exact commit + workflow run. ## Compromised-release response -1. **Deprecate immediately**: `npm deprecate @agentic-sentinel/

@ +1. **Deprecate immediately**: `npm deprecate @git-agentic/sentinel-

@ "SECURITY: compromised — do not install"` for every affected package. 2. Point the dist-tag at the last known-good version (`npm dist-tag add - @agentic-sentinel/

@ alpha`). + @git-agentic/sentinel-

@ alpha`). 3. Request npm unpublish/security takedown through npm support if within policy; do not rely on it. 4. Rotate every credential the pipeline touched (npm token, corpus/policy diff --git a/docs/releases/v0.1.0-alpha.1.md b/docs/releases/v0.1.0-alpha.1.md index 38583d2..fcf2cce 100644 --- a/docs/releases/v0.1.0-alpha.1.md +++ b/docs/releases/v0.1.0-alpha.1.md @@ -15,27 +15,27 @@ path, a deny-by-default install sandbox, and agent-native tooling. ```bash # CLI + proxy (most users start here) -npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha +npm install -g @git-agentic/sentinel-cli@alpha @git-agentic/sentinel-proxy@alpha sentinel-proxy & # transparent auditing proxy on :4873 sentinel audit is-odd 3.0.1 # pre-install verdict, no code executed sentinel audit-tree package-lock.json --sbom sbom.json # agent hosts (MCP) -npm install -g @agentic-sentinel/mcp@alpha +npm install -g @git-agentic/sentinel-mcp@alpha # library / CI / steward -npm install @agentic-sentinel/core@alpha @agentic-sentinel/action@alpha @agentic-sentinel/steward@alpha +npm install @git-agentic/sentinel-core@alpha @git-agentic/sentinel-action@alpha @git-agentic/sentinel-steward@alpha ``` -All seven packages — `@agentic-sentinel/core`, `@agentic-sentinel/proxy`, -`@agentic-sentinel/sandbox`, `@agentic-sentinel/cli`, `@agentic-sentinel/mcp`, `@agentic-sentinel/steward`, -`@agentic-sentinel/action` — publish in lockstep as `0.1.0-alpha.1` under the +All seven packages — `@git-agentic/sentinel-core`, `@git-agentic/sentinel-proxy`, +`@git-agentic/sentinel-sandbox`, `@git-agentic/sentinel-cli`, `@git-agentic/sentinel-mcp`, `@git-agentic/sentinel-steward`, +`@git-agentic/sentinel-action` — publish in lockstep as `0.1.0-alpha.1` under the `alpha` dist-tag, Apache-2.0, Node ≥ 22. ## What's in this release -**Deterministic audit engine (`@agentic-sentinel/core`).** Ten pure heuristic rules +**Deterministic audit engine (`@git-agentic/sentinel-core`).** Ten pure heuristic rules (install-scripts, secret-exfil, network-egress, obfuscation, provenance, typosquat, release-anomaly, known-advisory, known-vulnerability CVE ranges, and the dataflow-correlated `native-payload-loader`), raw-byte magic @@ -45,7 +45,7 @@ served bytes, npm/yarn/pnpm lockfile parsing, CycloneDX 1.6 SBOM export, and signed DSSE audit attestations. Same input + same policy ⇒ same score, always; the optional LLM adapter can only annotate, never set a verdict. -**Authoritative registry (`@agentic-sentinel/proxy`).** A transparent mirror of +**Authoritative registry (`@git-agentic/sentinel-proxy`).** A transparent mirror of public npm (only `dist.tarball` URLs rewritten) plus a native write path: `npm publish` against Sentinel is audited **synchronously** and gated by signed policy (`publishGate`, default block) before any byte is served. @@ -57,7 +57,7 @@ history), release-cooldown and quarantine serve-time overlays, signed role-token auth, SSRF origin pinning, byte caps, and opt-in SQLite history/metrics. -**Verified namespace steward (`@agentic-sentinel/steward`).** Exact-apex DNS TXT +**Verified namespace steward (`@git-agentic/sentinel-steward`).** Exact-apex DNS TXT claim challenges, three-tier grandfathering against upstream evidence, claimant-key-signed transfers with 30-day timelocks, renewal/freeze lifecycle, and atomic Ed25519-signed claim/retraction corpus releases that @@ -69,7 +69,7 @@ dist-tags, legacy login/whoami, and npm's `-rev` unpublish dance mapped onto time-locked retraction. The compat suite drives the four real client binaries (install, publish, and every mutation each client exposes) in CI. -**Capability sandbox (`@agentic-sentinel/sandbox`).** Deny-by-default install-time +**Capability sandbox (`@git-agentic/sentinel-sandbox`).** Deny-by-default install-time containment behind one approved-capability model: - **macOS (Seatbelt):** fully enforced — write floor, `$HOME` read denial, @@ -82,21 +82,21 @@ containment behind one approved-capability model: does not run lifecycle scripts, by posture). Without the compiled helper the exec floor is **advisory** and announced by a one-time notice; compile it explicitly with - `node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs` + `node node_modules/@git-agentic/sentinel-sandbox/scripts/build-native.mjs` (Linux + `cc`). See ADR-0052. - Any other platform: fail-closed (no sandbox ⇒ enforced operations refuse to run unsandboxed). -**CLI (`@agentic-sentinel/cli`).** `sentinel audit`/`audit-tree`/`explain`/`scan`, +**CLI (`@git-agentic/sentinel-cli`).** `sentinel audit`/`audit-tree`/`explain`/`scan`, registry-redirected `install`/`npx`, sandbox-enforced `install --enforce`, sandboxed one-shot `exec`, policy init/validate/preview/keygen/sign/verify, token minting, attestations, stats/history. -**MCP server (`@agentic-sentinel/mcp`).** Stdio Model Context Protocol server for +**MCP server (`@git-agentic/sentinel-mcp`).** Stdio Model Context Protocol server for agent hosts: six read tools plus one request-only approval tool — an agent can ask, only a human can grant. -**GitHub Action (`@agentic-sentinel/action`, bin `sentinel-ci`).** Self-boots the +**GitHub Action (`@git-agentic/sentinel-action`, bin `sentinel-ci`).** Self-boots the proxy in-process, audits the lockfile, uploads a CycloneDX SBOM, and posts an idempotent PR verdict comment. @@ -124,7 +124,7 @@ an idempotent PR verdict comment. ## Upgrading and feedback Alphas are fix-forward: update with -`npm install -g @agentic-sentinel/cli@alpha @agentic-sentinel/proxy@alpha` (repeat per +`npm install -g @git-agentic/sentinel-cli@alpha @git-agentic/sentinel-proxy@alpha` (repeat per package) — version numbers are never reused. File bugs, detection gaps, and feature requests at [github.com/git-agentic/pkg-registry/issues](https://github.com/git-agentic/pkg-registry/issues) diff --git a/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md b/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md index 171c546..6c588f7 100644 --- a/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md +++ b/docs/superpowers/plans/2026-07-12-native-payload-loader-detection.md @@ -6,7 +6,7 @@ **Architecture:** Three layered deliverables. **A** adds raw-byte magic classification to the extractor and threads the results into rules via a policy-independent `ExtractionObservations` channel. **B** adds an acorn-based `native-payload-loader` rule that correlates READ→DECODE→WRITE→LAUNCH with bounded local dataflow and escalates to critical only when the launched target is taint-reachable from a packaged read. **D** overlays a cooldown block at serve time (no wall-clock in the engine). **E** adds `sentinel exec -- ` running under the existing sandbox. A+B are the first independently shippable milestone; they close the zero-day. -**Tech Stack:** Node 24 + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`), Express 5, `tar` 7, `acorn` + `acorn-walk` (new — `@agentic-sentinel/core`'s first parser deps), tests on `node:test` + `tsx`. +**Tech Stack:** Node 24 + TypeScript, npm workspaces (`core`, `proxy`, `sandbox`, `cli`), Express 5, `tar` 7, `acorn` + `acorn-walk` (new — `@git-agentic/sentinel-core`'s first parser deps), tests on `node:test` + `tsx`. ## Global Constraints @@ -1241,7 +1241,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; @@ -1448,7 +1448,7 @@ git commit -m "feat(core): releaseCooldown policy field with fail-closed validat import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { cooldownDecision, resolvePublishTime, applyCooldown } from "../src/cooldown.js"; -import type { EnterprisePolicy, AuditReport } from "@agentic-sentinel/core"; +import type { EnterprisePolicy, AuditReport } from "@git-agentic/sentinel-core"; const NOW = Date.parse("2026-07-12T00:00:00Z"); const pol = (cd?: object): EnterprisePolicy => ({ schema: 1, version: "t", scoring: { severityWeight: { info:0,low:4,medium:12,high:25,critical:55 }, diffMultiplier:1.6, thresholds:{allow:80,warn:50}, hardBlockSeverity:"critical" }, rules:{disabled:[]}, allow:[], deny:[], privateNamespaces:[], ...(cd ? { releaseCooldown: cd } : {}) } as EnterprisePolicy); @@ -1506,7 +1506,7 @@ Expected: FAIL — module not found. ```ts // packages/proxy/src/cooldown.ts -import { matchPackage, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { matchPackage, type AuditReport, type EnterprisePolicy } from "@git-agentic/sentinel-core"; const HOUR_MS = 3_600_000; @@ -1574,7 +1574,7 @@ Reuse the Task 7 harness verbatim (imports + `ensureFixtures`), but give `startS ```ts // packages/proxy/test/cooldown-e2e.test.ts // (same imports + ensureFixtures + tarballUrl as payload-loader-e2e.test.ts) -import { parsePolicy } from "@agentic-sentinel/core"; +import { parsePolicy } from "@git-agentic/sentinel-core"; // leftpad-lite@1.0.1 carries a fixed `time` in the fixture registry (Step 2 adds it if absent). const PUBLISHED = "2026-07-10T00:00:00Z"; @@ -1854,7 +1854,7 @@ Expected (darwin): FAIL — unknown command `exec`. In `packages/cli/src/index.ts`, add `scrubEnv` to the existing sandbox import (it is already exported from `packages/sandbox/src/index.ts` — no export change needed): ```ts -import { createSandbox, runLifecycleScripts, scrubEnv } from "@agentic-sentinel/sandbox"; +import { createSandbox, runLifecycleScripts, scrubEnv } from "@git-agentic/sentinel-sandbox"; ``` Register the command (near the `run-scripts` command): ```ts diff --git a/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md b/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md index e7b26ea..d3aa28b 100644 --- a/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md +++ b/docs/superpowers/specs/2026-07-12-native-payload-loader-detection-design.md @@ -154,7 +154,7 @@ before UTF-8 conversion**, for **every** file entry regardless of size. New pure rule `packages/core/src/rules/native-payload-loader.ts`, registered in `rules/index.ts`. Adds **acorn** as the first parser dependency of -`@agentic-sentinel/core`. +`@git-agentic/sentinel-core`. ### Primitives (per file, AST-based) diff --git a/package-lock.json b/package-lock.json index df8d999..307cca8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,34 +27,6 @@ "node": ">=22" } }, - "node_modules/@agentic-sentinel/action": { - "resolved": "packages/action", - "link": true - }, - "node_modules/@agentic-sentinel/cli": { - "resolved": "packages/cli", - "link": true - }, - "node_modules/@agentic-sentinel/core": { - "resolved": "packages/core", - "link": true - }, - "node_modules/@agentic-sentinel/mcp": { - "resolved": "packages/mcp", - "link": true - }, - "node_modules/@agentic-sentinel/proxy": { - "resolved": "packages/proxy", - "link": true - }, - "node_modules/@agentic-sentinel/sandbox": { - "resolved": "packages/sandbox", - "link": true - }, - "node_modules/@agentic-sentinel/steward": { - "resolved": "packages/steward", - "link": true - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", @@ -497,6 +469,34 @@ "node": ">=18" } }, + "node_modules/@git-agentic/sentinel-action": { + "resolved": "packages/action", + "link": true + }, + "node_modules/@git-agentic/sentinel-cli": { + "resolved": "packages/cli", + "link": true + }, + "node_modules/@git-agentic/sentinel-core": { + "resolved": "packages/core", + "link": true + }, + "node_modules/@git-agentic/sentinel-mcp": { + "resolved": "packages/mcp", + "link": true + }, + "node_modules/@git-agentic/sentinel-proxy": { + "resolved": "packages/proxy", + "link": true + }, + "node_modules/@git-agentic/sentinel-sandbox": { + "resolved": "packages/sandbox", + "link": true + }, + "node_modules/@git-agentic/sentinel-steward": { + "resolved": "packages/steward", + "link": true + }, "node_modules/@hono/node-server": { "version": "1.19.14", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", @@ -2024,12 +2024,12 @@ } }, "packages/action": { - "name": "@agentic-sentinel/action", + "name": "@git-agentic/sentinel-action", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", - "@agentic-sentinel/proxy": "0.1.0-alpha.1" + "@git-agentic/sentinel-core": "0.1.0-alpha.1", + "@git-agentic/sentinel-proxy": "0.1.0-alpha.1" }, "bin": { "sentinel-ci": "dist/index.js" @@ -2042,12 +2042,12 @@ } }, "packages/cli": { - "name": "@agentic-sentinel/cli", + "name": "@git-agentic/sentinel-cli", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", - "@agentic-sentinel/sandbox": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", + "@git-agentic/sentinel-sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, "bin": { @@ -2062,7 +2062,7 @@ } }, "packages/core": { - "name": "@agentic-sentinel/core", + "name": "@git-agentic/sentinel-core", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { @@ -2084,11 +2084,11 @@ } }, "packages/mcp": { - "name": "@agentic-sentinel/mcp", + "name": "@git-agentic/sentinel-mcp", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^3.23.8" }, @@ -2103,11 +2103,11 @@ } }, "packages/proxy": { - "name": "@agentic-sentinel/proxy", + "name": "@git-agentic/sentinel-proxy", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" @@ -2125,11 +2125,11 @@ } }, "packages/sandbox": { - "name": "@agentic-sentinel/sandbox", + "name": "@git-agentic/sentinel-sandbox", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1" + "@git-agentic/sentinel-core": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" @@ -2139,11 +2139,11 @@ } }, "packages/steward": { - "name": "@agentic-sentinel/steward", + "name": "@git-agentic/sentinel-steward", "version": "0.1.0-alpha.1", "license": "Apache-2.0", "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, diff --git a/packages/action/README.md b/packages/action/README.md index 5753016..6d5f9c1 100644 --- a/packages/action/README.md +++ b/packages/action/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/action +# @git-agentic/sentinel-action `sentinel-ci`: a self-contained CI runner for GitHub Actions. It boots the Sentinel proxy in-process against real npm, audits your lockfile, writes a @@ -9,7 +9,7 @@ idempotent PR comment body — no separately-running proxy needed. > without notice. Not production-ready. ```bash -npm install @agentic-sentinel/action@alpha +npm install @git-agentic/sentinel-action@alpha ``` This package is the engine behind the composite GitHub Action defined at the diff --git a/packages/action/package.json b/packages/action/package.json index 6224de0..cc4b249 100644 --- a/packages/action/package.json +++ b/packages/action/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/action", + "name": "@git-agentic/sentinel-action", "version": "0.1.0-alpha.1", "description": "Sentinel CI runner: self-booting dependency-tree audit for GitHub Actions (sentinel-ci) — audits a lockfile, writes a CycloneDX SBOM, and posts a PR verdict.", "license": "Apache-2.0", @@ -42,8 +42,8 @@ "sbom" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", - "@agentic-sentinel/proxy": "0.1.0-alpha.1" + "@git-agentic/sentinel-core": "0.1.0-alpha.1", + "@git-agentic/sentinel-proxy": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" diff --git a/packages/action/src/index.ts b/packages/action/src/index.ts index 6ec5744..72f7cee 100644 --- a/packages/action/src/index.ts +++ b/packages/action/src/index.ts @@ -1,8 +1,8 @@ #!/usr/bin/env node import { readFileSync, realpathSync } from "node:fs"; import { pathToFileURL } from "node:url"; -import { NpmUpstream, LocalFixtureUpstream, type Upstream } from "@agentic-sentinel/proxy"; -import { loadPolicy, DEFAULT_POLICY, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { NpmUpstream, LocalFixtureUpstream, type Upstream } from "@git-agentic/sentinel-proxy"; +import { loadPolicy, DEFAULT_POLICY, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { runCi } from "./run.js"; function env(name: string, fallback = ""): string { @@ -47,7 +47,7 @@ async function main(): Promise { } // Run only when invoked as the entrypoint (bin shim or `node dist/index.js`), -// never on import — the same guard as @agentic-sentinel/proxy and @agentic-sentinel/mcp. +// never on import — the same guard as @git-agentic/sentinel-proxy and @git-agentic/sentinel-mcp. function isEntrypoint(): boolean { const arg = process.argv[1]; if (!arg) return false; diff --git a/packages/action/src/report.ts b/packages/action/src/report.ts index b516fe5..8373923 100644 --- a/packages/action/src/report.ts +++ b/packages/action/src/report.ts @@ -1,5 +1,5 @@ -import type { TreeAuditResult, TreePackageRow } from "@agentic-sentinel/core"; -import { remediationHint } from "@agentic-sentinel/core"; +import type { TreeAuditResult, TreePackageRow } from "@git-agentic/sentinel-core"; +import { remediationHint } from "@git-agentic/sentinel-core"; export const REPORT_MARKER = ""; diff --git a/packages/action/src/run.ts b/packages/action/src/run.ts index 5fb62ed..f33e786 100644 --- a/packages/action/src/run.ts +++ b/packages/action/src/run.ts @@ -5,8 +5,8 @@ import type { Server } from "node:http"; import { createServer, AuditStore, ApprovalStore, PrivatePackageStore, ViolationStore, ApprovalRequestStore, type Upstream, -} from "@agentic-sentinel/proxy"; -import { parseAnyLockfile, toCycloneDX, DEFAULT_POLICY, type EnterprisePolicy, type TreeAuditResult } from "@agentic-sentinel/core"; +} from "@git-agentic/sentinel-proxy"; +import { parseAnyLockfile, toCycloneDX, DEFAULT_POLICY, type EnterprisePolicy, type TreeAuditResult } from "@git-agentic/sentinel-core"; import { renderPrComment } from "./report.js"; export interface RunCiOptions { diff --git a/packages/action/test/report.test.ts b/packages/action/test/report.test.ts index 7f6d5d0..7b11858 100644 --- a/packages/action/test/report.test.ts +++ b/packages/action/test/report.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { renderPrComment, REPORT_MARKER } from "../src/report.js"; -import type { TreeAuditResult } from "@agentic-sentinel/core"; +import type { TreeAuditResult } from "@git-agentic/sentinel-core"; const result: TreeAuditResult = { aggregate: { diff --git a/packages/action/test/run-e2e.test.ts b/packages/action/test/run-e2e.test.ts index f0f9d19..d079c4e 100644 --- a/packages/action/test/run-e2e.test.ts +++ b/packages/action/test/run-e2e.test.ts @@ -5,7 +5,7 @@ import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; import { describe, test } from "node:test"; -import { LocalFixtureUpstream } from "@agentic-sentinel/proxy"; +import { LocalFixtureUpstream } from "@git-agentic/sentinel-proxy"; import { runCi } from "../src/run.js"; const HERE = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/cli/README.md b/packages/cli/README.md index b586d3c..933bdfc 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/cli +# @git-agentic/sentinel-cli The Sentinel CLI: pre-install audit verdicts (`sentinel audit`), whole-tree lockfile audits with SBOM export (`sentinel audit-tree`), registry-redirected @@ -10,14 +10,14 @@ authoring/signing, and signed audit attestations. > without notice. Not production-ready. ```bash -npm install -g @agentic-sentinel/cli@alpha +npm install -g @git-agentic/sentinel-cli@alpha sentinel --version -sentinel audit is-odd 3.0.1 # requires a running @agentic-sentinel/proxy +sentinel audit is-odd 3.0.1 # requires a running @git-agentic/sentinel-proxy sentinel audit-tree package-lock.json ``` -Most commands talk to a running [`@agentic-sentinel/proxy`](https://www.npmjs.com/package/@agentic-sentinel/proxy) +Most commands talk to a running [`@git-agentic/sentinel-proxy`](https://www.npmjs.com/package/@git-agentic/sentinel-proxy) (default `http://localhost:4873`, override with `SENTINEL_PROXY` or `-p`). See the [Sentinel repository](https://github.com/git-agentic/pkg-registry) for the full command reference. diff --git a/packages/cli/package.json b/packages/cli/package.json index 46ddb0a..403df51 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/cli", + "name": "@git-agentic/sentinel-cli", "version": "0.1.0-alpha.1", "description": "Sentinel CLI: pre-install audit verdicts, whole-tree lockfile audits, registry-redirected npm/npx, policy tooling, and sandbox-enforced installs.", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "sandbox" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", - "@agentic-sentinel/sandbox": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", + "@git-agentic/sentinel-sandbox": "0.1.0-alpha.1", "commander": "^15.0.0" }, "devDependencies": { diff --git a/packages/cli/src/enforce.ts b/packages/cli/src/enforce.ts index b130040..1a6d739 100644 --- a/packages/cli/src/enforce.ts +++ b/packages/cli/src/enforce.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import type { Manifest } from "./format.js"; /** Raised when enforcement cannot be guaranteed — the wrapper must fail closed (never run unsandboxed). */ diff --git a/packages/cli/src/format.ts b/packages/cli/src/format.ts index 2fb3f3e..22bfce6 100644 --- a/packages/cli/src/format.ts +++ b/packages/cli/src/format.ts @@ -1,4 +1,4 @@ -import type { AuditReport, Capability, CapabilityKind, Remediation, Severity, Verdict, TreeAuditResult, LintFinding } from "@agentic-sentinel/core"; +import type { AuditReport, Capability, CapabilityKind, Remediation, Severity, Verdict, TreeAuditResult, LintFinding } from "@git-agentic/sentinel-core"; const C = { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index a6bc983..29b03dc 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -18,8 +18,8 @@ import { toCycloneDX, signToken, verifyToken, type Role, buildAuditStatement, signAttestation, verifyAttestation, attestationKeyid, -} from "@agentic-sentinel/core"; -import { createSandbox, runLifecycleScripts, scrubEnv } from "@agentic-sentinel/sandbox"; +} from "@git-agentic/sentinel-core"; +import { createSandbox, runLifecycleScripts, scrubEnv } from "@git-agentic/sentinel-sandbox"; import { formatReport, formatManifest, verdictExitCode, formatTree, treeExitCode, formatViolations, formatStats, formatHistory, formatExplain, formatLint, formatPreview, type Manifest, type ViolationRow, type ExplainResult, type PreviewResult } from "./format.js"; const DEFAULT_PROXY = process.env.SENTINEL_PROXY ?? "http://localhost:4873"; diff --git a/packages/cli/src/script-shell.ts b/packages/cli/src/script-shell.ts index 38773b7..137cdd8 100644 --- a/packages/cli/src/script-shell.ts +++ b/packages/cli/src/script-shell.ts @@ -2,9 +2,9 @@ import { homedir } from "node:os"; import { realpathSync } from "node:fs"; import { pathToFileURL } from "node:url"; -import { createSandbox, scrubEnv, resolveProjectRoot } from "@agentic-sentinel/sandbox"; -import type { SandboxViolation } from "@agentic-sentinel/sandbox"; -import type { Capability } from "@agentic-sentinel/core"; +import { createSandbox, scrubEnv, resolveProjectRoot } from "@git-agentic/sentinel-sandbox"; +import type { SandboxViolation } from "@git-agentic/sentinel-sandbox"; +import type { Capability } from "@git-agentic/sentinel-core"; import { approvedCapsForManifest, isRootScript, commandFromArgv, EnforceError } from "./enforce.js"; import { parseApprovals } from "./index.js"; import type { Manifest } from "./format.js"; diff --git a/packages/cli/test/attest-cli-e2e.test.ts b/packages/cli/test/attest-cli-e2e.test.ts index c5f9e24..d0ef16b 100644 --- a/packages/cli/test/attest-cli-e2e.test.ts +++ b/packages/cli/test/attest-cli-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/audit-tree-cli-e2e.test.ts b/packages/cli/test/audit-tree-cli-e2e.test.ts index 07a5d40..9789d35 100644 --- a/packages/cli/test/audit-tree-cli-e2e.test.ts +++ b/packages/cli/test/audit-tree-cli-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/explain-cli-e2e.test.ts b/packages/cli/test/explain-cli-e2e.test.ts index 4fb6ad9..42bb8b8 100644 --- a/packages/cli/test/explain-cli-e2e.test.ts +++ b/packages/cli/test/explain-cli-e2e.test.ts @@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/format-tree.test.ts b/packages/cli/test/format-tree.test.ts index 1c5fb39..9f3ff4b 100644 --- a/packages/cli/test/format-tree.test.ts +++ b/packages/cli/test/format-tree.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { TreeAuditResult } from "@agentic-sentinel/core"; +import type { TreeAuditResult } from "@git-agentic/sentinel-core"; import { formatTree, treeExitCode } from "../src/format.js"; const gated: TreeAuditResult = { diff --git a/packages/cli/test/policy-authoring-cli-e2e.test.ts b/packages/cli/test/policy-authoring-cli-e2e.test.ts index 0c9be33..eef4072 100644 --- a/packages/cli/test/policy-authoring-cli-e2e.test.ts +++ b/packages/cli/test/policy-authoring-cli-e2e.test.ts @@ -10,8 +10,8 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; -import type { AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/cli/test/policy.test.ts b/packages/cli/test/policy.test.ts index f16b64c..5258fea 100644 --- a/packages/cli/test/policy.test.ts +++ b/packages/cli/test/policy.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { summarizePolicy } from "../src/index.js"; describe("summarizePolicy", () => { diff --git a/packages/cli/test/run-scripts.test.ts b/packages/cli/test/run-scripts.test.ts index e3447fb..787af7b 100644 --- a/packages/cli/test/run-scripts.test.ts +++ b/packages/cli/test/run-scripts.test.ts @@ -3,7 +3,7 @@ import { mkdtempSync, rmSync, writeFileSync, symlinkSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, test } from "node:test"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import { parseApprovals, unapprovedAtoms, readPackageFiles } from "../src/index.js"; const cap = (kind: string, target: string): Capability => ({ kind: kind as Capability["kind"], target, evidence: [] }); diff --git a/packages/cli/test/stats-history-cli-e2e.test.ts b/packages/cli/test/stats-history-cli-e2e.test.ts index b92b794..1a67293 100644 --- a/packages/cli/test/stats-history-cli-e2e.test.ts +++ b/packages/cli/test/stats-history-cli-e2e.test.ts @@ -8,8 +8,8 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; -import type { AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/core/README.md b/packages/core/README.md index c4a8354..97e6088 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/core +# @git-agentic/sentinel-core The Sentinel audit engine: deterministic heuristic rules, scoring, the audit data model, multi-format lockfile parsing (npm/yarn/pnpm), CycloneDX 1.6 SBOM @@ -9,11 +9,11 @@ that can only ever *enrich* — never set — a score. > without notice. Not production-ready. ```bash -npm install @agentic-sentinel/core@alpha +npm install @git-agentic/sentinel-core@alpha ``` ```ts -import { runAudit, score, DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { runAudit, score, DEFAULT_POLICY } from "@git-agentic/sentinel-core"; ``` The engine is fully offline and deterministic: same input + same policy ⇒ same diff --git a/packages/core/package.json b/packages/core/package.json index f247742..51b4ec6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/core", + "name": "@git-agentic/sentinel-core", "version": "0.1.0-alpha.1", "description": "Sentinel audit engine: deterministic heuristic rules, scoring, data model, lockfile parsing, SBOM export, and pluggable LLM adapter.", "license": "Apache-2.0", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index a2e7e79..8c54b8f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,4 @@ -/** @agentic-sentinel/core — deterministic npm package audit engine. */ +/** @git-agentic/sentinel-core — deterministic npm package audit engine. */ export * from "./types.js"; export { score, severityRank, POLICY_SYNTHESIZED_RULE_IDS } from "./score.js"; diff --git a/packages/core/test/package-contents.test.ts b/packages/core/test/package-contents.test.ts index 5a62aee..73f90d4 100644 --- a/packages/core/test/package-contents.test.ts +++ b/packages/core/test/package-contents.test.ts @@ -59,7 +59,7 @@ function packList(pkgDir: string): string[] { } for (const ws of WORKSPACES) { - test(`@agentic-sentinel/${ws} tarball contains only runtime files`, () => { + test(`@git-agentic/sentinel-${ws} tarball contains only runtime files`, () => { const pkgDir = join(repoRoot, "packages", ws); assert.ok( existsSync(join(pkgDir, "dist", "index.js")), @@ -73,10 +73,10 @@ for (const ws of WORKSPACES) { if (re.test(f)) violations.push(`${f} (${name})`); } } - assert.deepEqual(violations, [], `forbidden files in @agentic-sentinel/${ws} tarball:\n ${violations.join("\n ")}`); + assert.deepEqual(violations, [], `forbidden files in @git-agentic/sentinel-${ws} tarball:\n ${violations.join("\n ")}`); for (const req of REQUIRED[ws]) { - assert.ok(files.includes(req), `@agentic-sentinel/${ws} tarball is missing required runtime file: ${req}`); + assert.ok(files.includes(req), `@git-agentic/sentinel-${ws} tarball is missing required runtime file: ${req}`); } }); } diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 6f0cc95..cfe8ba6 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/mcp +# @git-agentic/sentinel-mcp `sentinel-mcp`: a stdio [Model Context Protocol](https://modelcontextprotocol.io/) server exposing Sentinel's pre-install audit tools to agent hosts. It is a @@ -9,7 +9,7 @@ only write tool *requests* approval; it can never grant one. > without notice. Not production-ready. ```bash -npm install -g @agentic-sentinel/mcp@alpha +npm install -g @git-agentic/sentinel-mcp@alpha ``` MCP client configuration: diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 3d4ef36..521bf8b 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/mcp", + "name": "@git-agentic/sentinel-mcp", "version": "0.1.0-alpha.1", "description": "Sentinel MCP server: agent-native pre-install audit tools backed by the Sentinel proxy (stdio Model Context Protocol server).", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "npm-audit" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^3.23.8" }, diff --git a/packages/mcp/src/client.ts b/packages/mcp/src/client.ts index 4398e45..d511757 100644 --- a/packages/mcp/src/client.ts +++ b/packages/mcp/src/client.ts @@ -1,4 +1,4 @@ -import type { AuditReport, Remediation } from "@agentic-sentinel/core"; +import type { AuditReport, Remediation } from "@git-agentic/sentinel-core"; export class ProxyError extends Error { constructor(message: string, readonly status?: number) { diff --git a/packages/mcp/src/format.ts b/packages/mcp/src/format.ts index 9a21829..ab10fca 100644 --- a/packages/mcp/src/format.ts +++ b/packages/mcp/src/format.ts @@ -1,4 +1,4 @@ -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; export function summarizeAudit(r: AuditReport, quarantined: boolean): string { const lines = [ diff --git a/packages/mcp/src/tools.ts b/packages/mcp/src/tools.ts index 84aa00c..622411e 100644 --- a/packages/mcp/src/tools.ts +++ b/packages/mcp/src/tools.ts @@ -1,6 +1,6 @@ import { readFileSync } from "node:fs"; import { z } from "zod"; -import { parseLockfile } from "@agentic-sentinel/core"; +import { parseLockfile } from "@git-agentic/sentinel-core"; import type { ProxyClient } from "./client.js"; import { summarizeAudit } from "./format.js"; diff --git a/packages/mcp/test/client-auth.test.ts b/packages/mcp/test/client-auth.test.ts index ffb808b..7cef3a6 100644 --- a/packages/mcp/test/client-auth.test.ts +++ b/packages/mcp/test/client-auth.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/client.test.ts b/packages/mcp/test/client.test.ts index c46c36b..1ca8a2b 100644 --- a/packages/mcp/test/client.test.ts +++ b/packages/mcp/test/client.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/server-e2e.test.ts b/packages/mcp/test/server-e2e.test.ts index 02447d3..5d88983 100644 --- a/packages/mcp/test/server-e2e.test.ts +++ b/packages/mcp/test/server-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/mcp/test/tools.test.ts b/packages/mcp/test/tools.test.ts index c94ab0b..f38f73d 100644 --- a/packages/mcp/test/tools.test.ts +++ b/packages/mcp/test/tools.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken } from "@git-agentic/sentinel-core"; import { createServer } from "../../proxy/src/server.js"; import { AuditStore } from "../../proxy/src/store.js"; import { LocalFixtureUpstream } from "../../proxy/src/upstream.js"; diff --git a/packages/proxy/README.md b/packages/proxy/README.md index 4f24fa3..03fbdc2 100644 --- a/packages/proxy/README.md +++ b/packages/proxy/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/proxy +# @git-agentic/sentinel-proxy The Sentinel registry proxy: an Express server that transparently serves npm packages while intercepting and auditing every tarball before install-time @@ -10,7 +10,7 @@ npm compatibility surface (packuments, dist-tags, unpublish-as-retraction). > without notice. Not production-ready. ```bash -npm install -g @agentic-sentinel/proxy@alpha +npm install -g @git-agentic/sentinel-proxy@alpha sentinel-proxy # starts the proxy on :4873 ``` diff --git a/packages/proxy/package.json b/packages/proxy/package.json index 6fdb999..a610897 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/proxy", + "name": "@git-agentic/sentinel-proxy", "version": "0.1.0-alpha.1", "description": "Sentinel registry proxy: transparently serves npm packages while intercepting and auditing each tarball, with an authoritative native publish path, verified claims, and time-locked retraction.", "license": "Apache-2.0", @@ -44,7 +44,7 @@ "package-retraction" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "commander": "^15.0.0", "express": "^5.2.1", "express-rate-limit": "^8.5.2" diff --git a/packages/proxy/src/approval-requests.ts b/packages/proxy/src/approval-requests.ts index 38ca194..14950b4 100644 --- a/packages/proxy/src/approval-requests.ts +++ b/packages/proxy/src/approval-requests.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; export interface ApprovalRequest { name: string; diff --git a/packages/proxy/src/approvals.ts b/packages/proxy/src/approvals.ts index 9baa385..9d2c622 100644 --- a/packages/proxy/src/approvals.ts +++ b/packages/proxy/src/approvals.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import { cmpSemver } from "./upstream.js"; export type ApprovalDecision = "approved" | "denied"; diff --git a/packages/proxy/src/authz.ts b/packages/proxy/src/authz.ts index f4f7a98..a17dad9 100644 --- a/packages/proxy/src/authz.ts +++ b/packages/proxy/src/authz.ts @@ -1,5 +1,5 @@ import type { Request, Response, RequestHandler } from "express"; -import { verifyToken, type Role } from "@agentic-sentinel/core"; +import { verifyToken, type Role } from "@git-agentic/sentinel-core"; /** Build the authz layer. `publicKeyPem` undefined ⇒ auth disabled (pass-through). */ export function makeAuthz(publicKeyPem: string | undefined): { enabled: boolean; requireRole(roles: Role[]): RequestHandler } { diff --git a/packages/proxy/src/cooldown.ts b/packages/proxy/src/cooldown.ts index f6b0e78..99d6753 100644 --- a/packages/proxy/src/cooldown.ts +++ b/packages/proxy/src/cooldown.ts @@ -1,4 +1,4 @@ -import { matchPackage, type AuditReport, type EnterprisePolicy, type ScoredFinding } from "@agentic-sentinel/core"; +import { matchPackage, type AuditReport, type EnterprisePolicy, type ScoredFinding } from "@git-agentic/sentinel-core"; const HOUR_MS = 3_600_000; diff --git a/packages/proxy/src/history-db.ts b/packages/proxy/src/history-db.ts index d38d12a..10eeafc 100644 --- a/packages/proxy/src/history-db.ts +++ b/packages/proxy/src/history-db.ts @@ -1,6 +1,6 @@ import { createRequire } from "node:module"; import { createHash, randomUUID } from "node:crypto"; -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import type { ViolationRecord } from "./violations.js"; export interface HistorySummary { diff --git a/packages/proxy/src/index.ts b/packages/proxy/src/index.ts index f61b5b7..9577b00 100644 --- a/packages/proxy/src/index.ts +++ b/packages/proxy/src/index.ts @@ -25,7 +25,7 @@ import { type Advisory, type RetractionCorpus, type VulnAdvisory, -} from "@agentic-sentinel/core"; +} from "@git-agentic/sentinel-core"; import { createServer, type ProxyPolicy } from "./server.js"; import { AuditStore } from "./store.js"; import { ApprovalStore } from "./approvals.js"; diff --git a/packages/proxy/src/private-store.ts b/packages/proxy/src/private-store.ts index 4d3cfe0..359df89 100644 --- a/packages/proxy/src/private-store.ts +++ b/packages/proxy/src/private-store.ts @@ -2,7 +2,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSy import { createHash, randomUUID } from "node:crypto"; import { join } from "node:path"; import { Buffer } from "node:buffer"; -import type { Audit, RetractionAdvisory, RetractionReason, VerifiedClaim } from "@agentic-sentinel/core"; +import type { Audit, RetractionAdvisory, RetractionReason, VerifiedClaim } from "@git-agentic/sentinel-core"; import { cmpSemver } from "./upstream.js"; export interface StoredVersion { @@ -32,7 +32,7 @@ export interface PrivatePackument { _sentinel?: { retractions: Record }; } -export type { RetractionAdvisory, RetractionReason } from "@agentic-sentinel/core"; +export type { RetractionAdvisory, RetractionReason } from "@git-agentic/sentinel-core"; export interface RetractionTombstone { retractedAt: string; diff --git a/packages/proxy/src/reconcile.ts b/packages/proxy/src/reconcile.ts index 13b0258..cf81785 100644 --- a/packages/proxy/src/reconcile.ts +++ b/packages/proxy/src/reconcile.ts @@ -1,4 +1,4 @@ -import { capabilityAtom, type Capability } from "@agentic-sentinel/core"; +import { capabilityAtom, type Capability } from "@git-agentic/sentinel-core"; import type { Approval } from "./approvals.js"; export type ApprovalState = "approved" | "inherited" | "required" | "denied" | "n-a"; diff --git a/packages/proxy/src/registry-mode.ts b/packages/proxy/src/registry-mode.ts index 15c7e9b..9fcedc1 100644 --- a/packages/proxy/src/registry-mode.ts +++ b/packages/proxy/src/registry-mode.ts @@ -1,5 +1,5 @@ import { writeFileSync } from "node:fs"; -import type { ClaimCorpus, EnterprisePolicy } from "@agentic-sentinel/core"; +import type { ClaimCorpus, EnterprisePolicy } from "@git-agentic/sentinel-core"; import type { PrivatePackageStore } from "./private-store.js"; import { EMPTY_CLAIM_CORPUS, source } from "./resolution.js"; import type { RegistryMode } from "./server.js"; diff --git a/packages/proxy/src/resolution.ts b/packages/proxy/src/resolution.ts index e77abbf..ddb8055 100644 --- a/packages/proxy/src/resolution.ts +++ b/packages/proxy/src/resolution.ts @@ -6,10 +6,10 @@ import { type EnterprisePolicy, type ProvenanceIdentity, type VerifiedClaim, -} from "@agentic-sentinel/core"; +} from "@git-agentic/sentinel-core"; -export { EMPTY_CLAIM_CORPUS } from "@agentic-sentinel/core"; -export type { ClaimCorpus, VerifiedClaim } from "@agentic-sentinel/core"; +export { EMPTY_CLAIM_CORPUS } from "@git-agentic/sentinel-core"; +export type { ClaimCorpus, VerifiedClaim } from "@git-agentic/sentinel-core"; export type RegistrySource = "policy-private" | "verified-claim" | "public-mirror"; diff --git a/packages/proxy/src/server.ts b/packages/proxy/src/server.ts index e2efea7..f51f016 100644 --- a/packages/proxy/src/server.ts +++ b/packages/proxy/src/server.ts @@ -37,7 +37,7 @@ import { type RetractionAdvisory, type RetractionCorpus, type RetractionReason, -} from "@agentic-sentinel/core"; +} from "@git-agentic/sentinel-core"; import { AuditStore } from "./store.js"; import { resolvePublishTime, cooldownDecision, applyCooldown, blockOverlay } from "./cooldown.js"; import { diff --git a/packages/proxy/src/store.ts b/packages/proxy/src/store.ts index 25175ca..f32ec47 100644 --- a/packages/proxy/src/store.ts +++ b/packages/proxy/src/store.ts @@ -1,5 +1,5 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import type { HistoryDb } from "./history-db.js"; export interface StoredAudit { diff --git a/packages/proxy/src/upstream.ts b/packages/proxy/src/upstream.ts index a2a8023..b4bdcbe 100644 --- a/packages/proxy/src/upstream.ts +++ b/packages/proxy/src/upstream.ts @@ -4,7 +4,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { request as httpRequest } from "node:http"; import { request as httpsRequest } from "node:https"; -import type { RegistrySignature } from "@agentic-sentinel/core"; +import type { RegistrySignature } from "@git-agentic/sentinel-core"; import { assertAllowedTarballUrl } from "./net-config.js"; import { readBodyCapped } from "./limits.js"; diff --git a/packages/proxy/test/approval-requests-e2e.test.ts b/packages/proxy/test/approval-requests-e2e.test.ts index 8e8204f..b1f22f8 100644 --- a/packages/proxy/test/approval-requests-e2e.test.ts +++ b/packages/proxy/test/approval-requests-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-e2e.test.ts b/packages/proxy/test/audit-tree-e2e.test.ts index ea9f7bf..6a29ea5 100644 --- a/packages/proxy/test/audit-tree-e2e.test.ts +++ b/packages/proxy/test/audit-tree-e2e.test.ts @@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile); import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-integrity-e2e.test.ts b/packages/proxy/test/audit-tree-integrity-e2e.test.ts index aa65fdb..735de39 100644 --- a/packages/proxy/test/audit-tree-integrity-e2e.test.ts +++ b/packages/proxy/test/audit-tree-integrity-e2e.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type TreeAuditResult } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type TreeAuditResult } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/audit-tree-limits-e2e.test.ts b/packages/proxy/test/audit-tree-limits-e2e.test.ts index e920361..14fd9a2 100644 --- a/packages/proxy/test/audit-tree-limits-e2e.test.ts +++ b/packages/proxy/test/audit-tree-limits-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/auth-config.test.ts b/packages/proxy/test/auth-config.test.ts index cb92bc9..db15cd0 100644 --- a/packages/proxy/test/auth-config.test.ts +++ b/packages/proxy/test/auth-config.test.ts @@ -7,7 +7,7 @@ import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; import { describe, test } from "node:test"; -import { generateKeypair } from "@agentic-sentinel/core"; +import { generateKeypair } from "@git-agentic/sentinel-core"; import { validateAuthPublicKey } from "../src/auth-config.js"; const execFileAsync = promisify(execFile); diff --git a/packages/proxy/test/authz-e2e.test.ts b/packages/proxy/test/authz-e2e.test.ts index cfdabf6..129373a 100644 --- a/packages/proxy/test/authz-e2e.test.ts +++ b/packages/proxy/test/authz-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/authz-unit.test.ts b/packages/proxy/test/authz-unit.test.ts index 0d7c373..6fd5385 100644 --- a/packages/proxy/test/authz-unit.test.ts +++ b/packages/proxy/test/authz-unit.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { generateKeypair, signToken, type Role } from "@agentic-sentinel/core"; +import { generateKeypair, signToken, type Role } from "@git-agentic/sentinel-core"; import { makeAuthz } from "../src/authz.js"; const { publicKey, privateKey } = generateKeypair(); diff --git a/packages/proxy/test/claim-corpus-startup.test.ts b/packages/proxy/test/claim-corpus-startup.test.ts index 5247f00..0373213 100644 --- a/packages/proxy/test/claim-corpus-startup.test.ts +++ b/packages/proxy/test/claim-corpus-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, signClaimCorpus, signRetractionCorpus } from "@agentic-sentinel/core"; +import { generateKeypair, signClaimCorpus, signRetractionCorpus } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const ROOT = join(HERE, "..", "..", ".."); diff --git a/packages/proxy/test/claim-lifecycle-e2e.test.ts b/packages/proxy/test/claim-lifecycle-e2e.test.ts index a76808c..f66e610 100644 --- a/packages/proxy/test/claim-lifecycle-e2e.test.ts +++ b/packages/proxy/test/claim-lifecycle-e2e.test.ts @@ -7,7 +7,7 @@ import type { AddressInfo } from "node:net"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { afterEach, describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, runAudit, type ClaimCorpus, type ClaimStatus, type EnterprisePolicy, type TrustedPublisher } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, runAudit, type ClaimCorpus, type ClaimStatus, type EnterprisePolicy, type TrustedPublisher } from "@git-agentic/sentinel-core"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { ApprovalStore } from "../src/approvals.js"; import { PrivatePackageStore } from "../src/private-store.js"; diff --git a/packages/proxy/test/coalesce-e2e.test.ts b/packages/proxy/test/coalesce-e2e.test.ts index d5eeb3f..64c104a 100644 --- a/packages/proxy/test/coalesce-e2e.test.ts +++ b/packages/proxy/test/coalesce-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/compatibility-e2e.test.ts b/packages/proxy/test/compatibility-e2e.test.ts index ea5e6c5..f619be0 100644 --- a/packages/proxy/test/compatibility-e2e.test.ts +++ b/packages/proxy/test/compatibility-e2e.test.ts @@ -6,7 +6,7 @@ import { after, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; import { gzipSync } from "node:zlib"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, integrityOfAlgo, runAudit, signToken, type ClaimCorpus, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, integrityOfAlgo, runAudit, signToken, type ClaimCorpus, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { ApprovalStore } from "../src/approvals.js"; diff --git a/packages/proxy/test/cooldown-e2e.test.ts b/packages/proxy/test/cooldown-e2e.test.ts index 3ea8ac2..e9d0b9d 100644 --- a/packages/proxy/test/cooldown-e2e.test.ts +++ b/packages/proxy/test/cooldown-e2e.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { parsePolicy } from "@agentic-sentinel/core"; +import { parsePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/cooldown.test.ts b/packages/proxy/test/cooldown.test.ts index 4e8ba5b..97c542f 100644 --- a/packages/proxy/test/cooldown.test.ts +++ b/packages/proxy/test/cooldown.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { cooldownDecision, resolvePublishTime, applyCooldown, blockOverlay } from "../src/cooldown.js"; -import type { EnterprisePolicy, AuditReport } from "@agentic-sentinel/core"; +import type { EnterprisePolicy, AuditReport } from "@git-agentic/sentinel-core"; const NOW = Date.parse("2026-07-12T00:00:00Z"); diff --git a/packages/proxy/test/enforce-e2e.test.ts b/packages/proxy/test/enforce-e2e.test.ts index 114dbd2..0c574e8 100644 --- a/packages/proxy/test/enforce-e2e.test.ts +++ b/packages/proxy/test/enforce-e2e.test.ts @@ -14,7 +14,7 @@ import { ApprovalStore } from "../src/approvals.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/explain-e2e.test.ts b/packages/proxy/test/explain-e2e.test.ts index 0e07a71..3ccce92 100644 --- a/packages/proxy/test/explain-e2e.test.ts +++ b/packages/proxy/test/explain-e2e.test.ts @@ -7,7 +7,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, runAudit, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, runAudit, integrityOf, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/history-db-queries.test.ts b/packages/proxy/test/history-db-queries.test.ts index f9eb715..428c1ce 100644 --- a/packages/proxy/test/history-db-queries.test.ts +++ b/packages/proxy/test/history-db-queries.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import type { ViolationRecord } from "../src/violations.js"; function rep(integrity: string, name: string, verdict: "allow" | "warn" | "block", finding: string | null, at: string): [AuditReport, string] { diff --git a/packages/proxy/test/history-db.test.ts b/packages/proxy/test/history-db.test.ts index 1ae875f..4e44d22 100644 --- a/packages/proxy/test/history-db.test.ts +++ b/packages/proxy/test/history-db.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import type { ViolationRecord } from "../src/violations.js"; function auditReport(over: Partial<{ integrity: string; name: string; version: string; verdict: "allow" | "warn" | "block"; score: number; finding: string; signature: string; provenance: string }> = {}): AuditReport { diff --git a/packages/proxy/test/history-endpoints-e2e.test.ts b/packages/proxy/test/history-endpoints-e2e.test.ts index fb86be0..c27b803 100644 --- a/packages/proxy/test/history-endpoints-e2e.test.ts +++ b/packages/proxy/test/history-endpoints-e2e.test.ts @@ -2,8 +2,8 @@ import assert from "node:assert/strict"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; -import type { AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/history-writethrough.test.ts b/packages/proxy/test/history-writethrough.test.ts index e180178..7327c72 100644 --- a/packages/proxy/test/history-writethrough.test.ts +++ b/packages/proxy/test/history-writethrough.test.ts @@ -3,7 +3,7 @@ import { describe, test } from "node:test"; import { HistoryDb } from "../src/history-db.js"; import { AuditStore } from "../src/store.js"; import { ViolationStore } from "../src/violations.js"; -import type { AuditReport } from "@agentic-sentinel/core"; +import type { AuditReport } from "@git-agentic/sentinel-core"; import type { ViolationRecord } from "../src/violations.js"; const report = { diff --git a/packages/proxy/test/known-advisory-e2e.test.ts b/packages/proxy/test/known-advisory-e2e.test.ts index c9b8c57..3b330cd 100644 --- a/packages/proxy/test/known-advisory-e2e.test.ts +++ b/packages/proxy/test/known-advisory-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type Advisory, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type Advisory, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/known-vulnerability-e2e.test.ts b/packages/proxy/test/known-vulnerability-e2e.test.ts index df311dd..1b5227a 100644 --- a/packages/proxy/test/known-vulnerability-e2e.test.ts +++ b/packages/proxy/test/known-vulnerability-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type VulnAdvisory, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type VulnAdvisory, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/payload-loader-e2e.test.ts b/packages/proxy/test/payload-loader-e2e.test.ts index 33240e0..3a005f5 100644 --- a/packages/proxy/test/payload-loader-e2e.test.ts +++ b/packages/proxy/test/payload-loader-e2e.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/policy-preview-e2e.test.ts b/packages/proxy/test/policy-preview-e2e.test.ts index e8b1329..f25d54c 100644 --- a/packages/proxy/test/policy-preview-e2e.test.ts +++ b/packages/proxy/test/policy-preview-e2e.test.ts @@ -2,8 +2,8 @@ import assert from "node:assert/strict"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, score } from "@agentic-sentinel/core"; -import type { Audit, AuditReport, EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, score } from "@git-agentic/sentinel-core"; +import type { Audit, AuditReport, EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/policy-startup.test.ts b/packages/proxy/test/policy-startup.test.ts index 497ec97..b0964dd 100644 --- a/packages/proxy/test/policy-startup.test.ts +++ b/packages/proxy/test/policy-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, signPolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signPolicy } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = join(HERE, "..", "..", ".."); diff --git a/packages/proxy/test/private-serve.test.ts b/packages/proxy/test/private-serve.test.ts index 7faf36c..65f0420 100644 --- a/packages/proxy/test/private-serve.test.ts +++ b/packages/proxy/test/private-serve.test.ts @@ -14,7 +14,7 @@ import { PrivatePackageStore } from "../src/private-store.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { LocalFixtureUpstream, type Upstream } from "../src/upstream.js"; -import { DEFAULT_POLICY, generateKeypair, runAudit, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, runAudit, integrityOf, type EnterprisePolicy } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/private-store.test.ts b/packages/proxy/test/private-store.test.ts index 97b9401..1b28d20 100644 --- a/packages/proxy/test/private-store.test.ts +++ b/packages/proxy/test/private-store.test.ts @@ -5,7 +5,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, test } from "node:test"; import { PrivatePackageStore } from "../src/private-store.js"; -import type { Audit } from "@agentic-sentinel/core"; +import type { Audit } from "@git-agentic/sentinel-core"; const audit = { schema: 3, meta: {}, findings: [], capabilities: [], capabilityDelta: null, engine: { version: "x", rules: [], mode: "full" }, auditedAt: "t", durationMs: 0 } as unknown as Audit; diff --git a/packages/proxy/test/provenance-verify.test.ts b/packages/proxy/test/provenance-verify.test.ts index 4d1c823..7210a04 100644 --- a/packages/proxy/test/provenance-verify.test.ts +++ b/packages/proxy/test/provenance-verify.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type EnterprisePolicy, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type EnterprisePolicy, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer, type ServerOptions } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/proxy.test.ts b/packages/proxy/test/proxy.test.ts index 22308ed..4f1b16a 100644 --- a/packages/proxy/test/proxy.test.ts +++ b/packages/proxy/test/proxy.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/public-base-url-e2e.test.ts b/packages/proxy/test/public-base-url-e2e.test.ts index 33d57bf..2bd2a62 100644 --- a/packages/proxy/test/public-base-url-e2e.test.ts +++ b/packages/proxy/test/public-base-url-e2e.test.ts @@ -7,7 +7,7 @@ import { request as httpRequest } from "node:http"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/publish.test.ts b/packages/proxy/test/publish.test.ts index 0482631..a2b9d4a 100644 --- a/packages/proxy/test/publish.test.ts +++ b/packages/proxy/test/publish.test.ts @@ -18,7 +18,7 @@ import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import type { ClaimCorpus } from "../src/resolution.js"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, type EnterprisePolicy } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/rate-limit-e2e.test.ts b/packages/proxy/test/rate-limit-e2e.test.ts index b10f658..ecda852 100644 --- a/packages/proxy/test/rate-limit-e2e.test.ts +++ b/packages/proxy/test/rate-limit-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { createRateLimiter } from "../src/rate-limit.js"; import { AuditStore } from "../src/store.js"; diff --git a/packages/proxy/test/reconcile.test.ts b/packages/proxy/test/reconcile.test.ts index 11cfc98..ee4d338 100644 --- a/packages/proxy/test/reconcile.test.ts +++ b/packages/proxy/test/reconcile.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import { reconcileApproval } from "../src/reconcile.js"; import type { Approval } from "../src/approvals.js"; diff --git a/packages/proxy/test/registry-migration.test.ts b/packages/proxy/test/registry-migration.test.ts index 1e0d5ba..e3215bd 100644 --- a/packages/proxy/test/registry-migration.test.ts +++ b/packages/proxy/test/registry-migration.test.ts @@ -8,7 +8,7 @@ import { join } from "node:path"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, type Audit, type ClaimCorpus } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, type Audit, type ClaimCorpus } from "@git-agentic/sentinel-core"; import { PrivatePackageStore } from "../src/private-store.js"; import { configureRegistryMode } from "../src/registry-mode.js"; import { exportNativeStore } from "../src/registry-export.js"; diff --git a/packages/proxy/test/registry-mode-startup.test.ts b/packages/proxy/test/registry-mode-startup.test.ts index 2f7d159..4d79428 100644 --- a/packages/proxy/test/registry-mode-startup.test.ts +++ b/packages/proxy/test/registry-mode-startup.test.ts @@ -5,7 +5,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, signClaimCorpus, type Audit } from "@agentic-sentinel/core"; +import { generateKeypair, signClaimCorpus, type Audit } from "@git-agentic/sentinel-core"; import { PrivatePackageStore } from "../src/private-store.js"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", ".."); diff --git a/packages/proxy/test/release-anomaly-e2e.test.ts b/packages/proxy/test/release-anomaly-e2e.test.ts index 72a368f..88d1276 100644 --- a/packages/proxy/test/release-anomaly-e2e.test.ts +++ b/packages/proxy/test/release-anomaly-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type AuditReport } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/resolution.test.ts b/packages/proxy/test/resolution.test.ts index 0323d60..3f68f21 100644 --- a/packages/proxy/test/resolution.test.ts +++ b/packages/proxy/test/resolution.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { EMPTY_CLAIM_CORPUS, normalizePackageName, diff --git a/packages/proxy/test/retraction-e2e.test.ts b/packages/proxy/test/retraction-e2e.test.ts index 13f4343..8facd7e 100644 --- a/packages/proxy/test/retraction-e2e.test.ts +++ b/packages/proxy/test/retraction-e2e.test.ts @@ -3,7 +3,7 @@ import { Buffer } from "node:buffer"; import type { Server } from "node:http"; import type { AddressInfo } from "node:net"; import { afterEach, describe, test } from "node:test"; -import { DEFAULT_POLICY, generateKeypair, integrityOf, retractionCorpusHashOfBytes, signToken, type Audit, type EnterprisePolicy, type RetractionCorpus } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, integrityOf, retractionCorpusHashOfBytes, signToken, type Audit, type EnterprisePolicy, type RetractionCorpus } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { ApprovalStore } from "../src/approvals.js"; diff --git a/packages/proxy/test/signature-verify.test.ts b/packages/proxy/test/signature-verify.test.ts index 0c022d0..c6e37cf 100644 --- a/packages/proxy/test/signature-verify.test.ts +++ b/packages/proxy/test/signature-verify.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type NpmSigningKey } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type NpmSigningKey } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/tree.test.ts b/packages/proxy/test/tree.test.ts index b26cb07..270b95c 100644 --- a/packages/proxy/test/tree.test.ts +++ b/packages/proxy/test/tree.test.ts @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type TreeAuditResult } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type TreeAuditResult } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/typosquat-e2e.test.ts b/packages/proxy/test/typosquat-e2e.test.ts index 6fa840f..2ac56d8 100644 --- a/packages/proxy/test/typosquat-e2e.test.ts +++ b/packages/proxy/test/typosquat-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/violation-enforce-e2e.test.ts b/packages/proxy/test/violation-enforce-e2e.test.ts index 805a611..6a529c1 100644 --- a/packages/proxy/test/violation-enforce-e2e.test.ts +++ b/packages/proxy/test/violation-enforce-e2e.test.ts @@ -26,7 +26,7 @@ import { ApprovalStore } from "../src/approvals.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; import { ViolationStore } from "../src/violations.js"; import { ApprovalRequestStore } from "../src/approval-requests.js"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport } from "@git-agentic/sentinel-core"; const HERE = dirname(fileURLToPath(import.meta.url)); const FIXTURES = join(HERE, "..", "..", "..", "fixtures"); diff --git a/packages/proxy/test/violations-e2e.test.ts b/packages/proxy/test/violations-e2e.test.ts index c8d3f03..0f2cce5 100644 --- a/packages/proxy/test/violations-e2e.test.ts +++ b/packages/proxy/test/violations-e2e.test.ts @@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process"; import { after, before, describe, test } from "node:test"; import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; -import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, generateKeypair, signToken, type AuditReport, type Role } from "@git-agentic/sentinel-core"; import { createServer, type ServerOptions } from "../src/server.js"; import { AuditStore } from "../src/store.js"; import { LocalFixtureUpstream } from "../src/upstream.js"; diff --git a/packages/proxy/test/violations-startup.test.ts b/packages/proxy/test/violations-startup.test.ts index 8eb963f..c48c9e3 100644 --- a/packages/proxy/test/violations-startup.test.ts +++ b/packages/proxy/test/violations-startup.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair } from "@agentic-sentinel/core"; +import { generateKeypair } from "@git-agentic/sentinel-core"; const execFileAsync = promisify(execFile); const HERE = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/sandbox/README.md b/packages/sandbox/README.md index 2c14ee1..55b8440 100644 --- a/packages/sandbox/README.md +++ b/packages/sandbox/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/sandbox +# @git-agentic/sentinel-sandbox The Sentinel capability sandbox: turns an approved capability set into enforced install-time least-privilege. `createSandbox()` selects **Seatbelt** @@ -10,7 +10,7 @@ with a fail-closed contract on any other platform. > without notice. Not production-ready. ```bash -npm install @agentic-sentinel/sandbox@alpha +npm install @git-agentic/sentinel-sandbox@alpha ``` ## Platform behavior in this alpha @@ -29,7 +29,7 @@ To opt in to Landlock exec-floor enforcement on Linux, compile the helper explicitly (requires `cc`): ```bash -node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs +node node_modules/@git-agentic/sentinel-sandbox/scripts/build-native.mjs ``` The helper is verified with an ABI probe before use; any failure falls back diff --git a/packages/sandbox/package.json b/packages/sandbox/package.json index 3702531..4668c51 100644 --- a/packages/sandbox/package.json +++ b/packages/sandbox/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/sandbox", + "name": "@git-agentic/sentinel-sandbox", "version": "0.1.0-alpha.1", "description": "Sentinel capability sandbox: generate an OS sandbox profile from approved capabilities and run lifecycle scripts under it (macOS Seatbelt / Linux bubblewrap, deny-by-default).", "license": "Apache-2.0", @@ -43,7 +43,7 @@ "least-privilege" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1" + "@git-agentic/sentinel-core": "0.1.0-alpha.1" }, "devDependencies": { "@types/node": "^24.13.2" diff --git a/packages/sandbox/src/bubblewrap.ts b/packages/sandbox/src/bubblewrap.ts index 9277e77..05932a8 100644 --- a/packages/sandbox/src/bubblewrap.ts +++ b/packages/sandbox/src/bubblewrap.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from "node:url"; import { dirname, join, sep } from "node:path"; import { generateBwrapArgs } from "./bwrap.js"; import type { Sandbox, SandboxResult } from "./types.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import { computeDenySet, landlockAllowPaths } from "./deny-set.js"; import { classifyViolation } from "./violation.js"; import { nodeInstallPrefix } from "./read-allow.js"; diff --git a/packages/sandbox/src/bwrap.ts b/packages/sandbox/src/bwrap.ts index e85885b..9e0fb64 100644 --- a/packages/sandbox/src/bwrap.ts +++ b/packages/sandbox/src/bwrap.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; +import { sensitivePathsFor, type Capability } from "@git-agentic/sentinel-core"; import { pathCovers } from "./path-cover.js"; import { expandHome, isSafeGrantTarget } from "./deny-set.js"; import { writeAllowFloor } from "./write-floor.js"; diff --git a/packages/sandbox/src/deny-set.ts b/packages/sandbox/src/deny-set.ts index 818e794..25e0128 100644 --- a/packages/sandbox/src/deny-set.ts +++ b/packages/sandbox/src/deny-set.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; +import { sensitivePathsFor, type Capability } from "@git-agentic/sentinel-core"; import { pathCovers } from "./path-cover.js"; import { execAllowFloor, linuxExecFloor } from "./exec-floor.js"; import { SENSITIVE_EXECUTABLES, execCarveOutPaths, classifyProcessTarget } from "./sensitive-executables.js"; diff --git a/packages/sandbox/src/env.ts b/packages/sandbox/src/env.ts index 777ba89..df9af58 100644 --- a/packages/sandbox/src/env.ts +++ b/packages/sandbox/src/env.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; /** Env-var names that look credential-bearing — dropped regardless of allowlist match. */ export const CREDENTIAL_ENV_RE = /_auth|authtoken|_password|passwd|token|secret|credential|api[_-]?key|access[_-]?key/i; diff --git a/packages/sandbox/src/profile.ts b/packages/sandbox/src/profile.ts index be12e2b..1e7631e 100644 --- a/packages/sandbox/src/profile.ts +++ b/packages/sandbox/src/profile.ts @@ -1,4 +1,4 @@ -import { sensitivePathsFor, type Capability } from "@agentic-sentinel/core"; +import { sensitivePathsFor, type Capability } from "@git-agentic/sentinel-core"; import { pathCovers } from "./path-cover.js"; import { canonicalizeMacPath, expandHome, isSafeGrantTarget } from "./deny-set.js"; import { writeAllowFloor } from "./write-floor.js"; diff --git a/packages/sandbox/src/runner.ts b/packages/sandbox/src/runner.ts index 75fe630..61905e8 100644 --- a/packages/sandbox/src/runner.ts +++ b/packages/sandbox/src/runner.ts @@ -2,7 +2,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import type { Sandbox } from "./types.js"; import { scrubEnv } from "./env.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; export interface ScriptResult { hook: string; diff --git a/packages/sandbox/src/seatbelt.ts b/packages/sandbox/src/seatbelt.ts index 4831ba4..7ed1131 100644 --- a/packages/sandbox/src/seatbelt.ts +++ b/packages/sandbox/src/seatbelt.ts @@ -2,7 +2,7 @@ import { spawnSync } from "node:child_process"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import type { Sandbox, SandboxResult } from "./types.js"; import { generateProfile } from "./profile.js"; import { computeDenySet } from "./deny-set.js"; diff --git a/packages/sandbox/src/types.ts b/packages/sandbox/src/types.ts index 486cb79..1ac1b68 100644 --- a/packages/sandbox/src/types.ts +++ b/packages/sandbox/src/types.ts @@ -1,4 +1,4 @@ -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; export interface SandboxViolation { /** The denied resource class the child hit. */ diff --git a/packages/sandbox/test/bubblewrap.test.ts b/packages/sandbox/test/bubblewrap.test.ts index 1abd9c5..12e6f13 100644 --- a/packages/sandbox/test/bubblewrap.test.ts +++ b/packages/sandbox/test/bubblewrap.test.ts @@ -9,7 +9,7 @@ import { describe, test } from "node:test"; import { BubblewrapSandbox } from "../src/bubblewrap.js"; import { runLifecycleScripts } from "../src/runner.js"; import { scrubEnv } from "../src/env.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; // dist sibling of the compiled bubblewrap.js; in the source tree the helper lands in // packages/sandbox/dist/landlock-exec after `npm run build`. @@ -304,7 +304,7 @@ describe("BubblewrapSandbox enforcement", { skip }, () => { }); test("missing Landlock helper: scripts still run on the advisory floor with a one-time notice (packaged-artifact state)", () => { - // The published @agentic-sentinel/sandbox tarball deliberately ships NO compiled + // The published @git-agentic/sentinel-sandbox tarball deliberately ships NO compiled // landlock-exec (source-only, no lifecycle-script compile). Reproduce that // state hermetically: copy the built dist/ WITHOUT the helper binary and // drive bubblewrap.js from the copy — its helper lookup (same-dir sibling) diff --git a/packages/sandbox/test/bwrap.test.ts b/packages/sandbox/test/bwrap.test.ts index 3bbae4d..2d400ad 100644 --- a/packages/sandbox/test/bwrap.test.ts +++ b/packages/sandbox/test/bwrap.test.ts @@ -2,7 +2,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { generateBwrapArgs } from "../src/bwrap.js"; import { SENSITIVE_EXECUTABLES } from "../src/sensitive-executables.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; const fs = (target: string): Capability => ({ kind: "filesystem", target, evidence: [] }); const net = (target: string): Capability => ({ kind: "network", target, evidence: [] }); diff --git a/packages/sandbox/test/deny-set.test.ts b/packages/sandbox/test/deny-set.test.ts index 7142b04..8d1edb1 100644 --- a/packages/sandbox/test/deny-set.test.ts +++ b/packages/sandbox/test/deny-set.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; import { computeDenySet, isSafeGrantTarget, landlockAllowPaths } from "../src/deny-set.js"; import { generateProfile } from "../src/profile.js"; import { generateBwrapArgs } from "../src/bwrap.js"; diff --git a/packages/sandbox/test/env.test.ts b/packages/sandbox/test/env.test.ts index a4549ba..cf7c946 100644 --- a/packages/sandbox/test/env.test.ts +++ b/packages/sandbox/test/env.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { scrubEnv, ENV_ALLOWLIST, CREDENTIAL_ENV_RE } from "../src/env.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; const envCap = (target: string): Capability => ({ kind: "env", target, evidence: [] }); diff --git a/packages/sandbox/test/profile.test.ts b/packages/sandbox/test/profile.test.ts index acec9e0..d551b75 100644 --- a/packages/sandbox/test/profile.test.ts +++ b/packages/sandbox/test/profile.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { describe, test } from "node:test"; import { generateProfile } from "../src/profile.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; const fs = (target: string): Capability => ({ kind: "filesystem", target, evidence: [] }); const net = (target: string): Capability => ({ kind: "network", target, evidence: [] }); diff --git a/packages/sandbox/test/runner.test.ts b/packages/sandbox/test/runner.test.ts index 4953f70..b3a3ef8 100644 --- a/packages/sandbox/test/runner.test.ts +++ b/packages/sandbox/test/runner.test.ts @@ -5,7 +5,7 @@ import { join } from "node:path"; import { describe, test } from "node:test"; import { runLifecycleScripts } from "../src/runner.js"; import type { Sandbox, SandboxResult } from "../src/types.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; function fakeSandbox(captured: NodeJS.ProcessEnv[]): Sandbox { return { run(_cmd, opts: { cwd: string; approved: Capability[]; homeDir: string; env?: NodeJS.ProcessEnv }): SandboxResult { diff --git a/packages/sandbox/test/seatbelt.test.ts b/packages/sandbox/test/seatbelt.test.ts index 91f4eed..6a74881 100644 --- a/packages/sandbox/test/seatbelt.test.ts +++ b/packages/sandbox/test/seatbelt.test.ts @@ -7,7 +7,7 @@ import { describe, test } from "node:test"; import { SeatbeltSandbox } from "../src/seatbelt.js"; import { runLifecycleScripts } from "../src/runner.js"; import { scrubEnv } from "../src/env.js"; -import type { Capability } from "@agentic-sentinel/core"; +import type { Capability } from "@git-agentic/sentinel-core"; const darwin = process.platform === "darwin"; diff --git a/packages/steward/README.md b/packages/steward/README.md index 3417478..c3c7fbf 100644 --- a/packages/steward/README.md +++ b/packages/steward/README.md @@ -1,4 +1,4 @@ -# @agentic-sentinel/steward +# @git-agentic/sentinel-steward `sentinel-steward`: the Sentinel namespace-claim steward — an authenticated operational service for exact-apex DNS TXT claim challenges, three-tier @@ -10,7 +10,7 @@ retraction-corpus releases that Sentinel proxies consume offline. > without notice. Not production-ready. ```bash -npm install -g @agentic-sentinel/steward@alpha +npm install -g @git-agentic/sentinel-steward@alpha ``` All four variables are required: diff --git a/packages/steward/package.json b/packages/steward/package.json index f1a6626..539542d 100644 --- a/packages/steward/package.json +++ b/packages/steward/package.json @@ -1,5 +1,5 @@ { - "name": "@agentic-sentinel/steward", + "name": "@git-agentic/sentinel-steward", "version": "0.1.0-alpha.1", "description": "Sentinel namespace-claim steward: DNS TXT claim verification, renewal/freeze lifecycle, timelocked transfers, and Ed25519-signed claim/retraction corpus releases.", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "npm-registry" ], "dependencies": { - "@agentic-sentinel/core": "0.1.0-alpha.1", + "@git-agentic/sentinel-core": "0.1.0-alpha.1", "express": "^5.2.1", "express-rate-limit": "^8.5.2" }, diff --git a/packages/steward/src/server.ts b/packages/steward/src/server.ts index 994dd45..a9d1728 100644 --- a/packages/steward/src/server.ts +++ b/packages/steward/src/server.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import express, { type Request, type Response } from "express"; import { rateLimit } from "express-rate-limit"; import { ClaimSteward, type ClaimApplicationInput, type TxtResolver } from "./steward.js"; -import type { RetractionAdvisory } from "@agentic-sentinel/core"; +import type { RetractionAdvisory } from "@git-agentic/sentinel-core"; export interface StewardServerOptions { steward: ClaimSteward; diff --git a/packages/steward/src/steward.ts b/packages/steward/src/steward.ts index 9d8d97e..080f561 100644 --- a/packages/steward/src/steward.ts +++ b/packages/steward/src/steward.ts @@ -17,7 +17,7 @@ import { signRetractionCorpus, type RetractionAdvisory, type RetractionCorpus, -} from "@agentic-sentinel/core"; +} from "@git-agentic/sentinel-core"; export type GrandfatherTier = 1 | 2 | 3; export type TxtResolver = (domain: string) => Promise; diff --git a/packages/steward/test/steward.test.ts b/packages/steward/test/steward.test.ts index f2c6b71..2fe55ee 100644 --- a/packages/steward/test/steward.test.ts +++ b/packages/steward/test/steward.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { basename, join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, test } from "node:test"; -import { generateKeypair, parseClaimCorpus, verifyClaimCorpusBytes, parseRetractionCorpus, verifyRetractionCorpusBytes } from "@agentic-sentinel/core"; +import { generateKeypair, parseClaimCorpus, verifyClaimCorpusBytes, parseRetractionCorpus, verifyRetractionCorpusBytes } from "@git-agentic/sentinel-core"; import { ClaimSteward, corroboratesClaimDomain, signTransferRequest, type UpstreamClaimLookup } from "../src/steward.js"; import { createStewardServer } from "../src/server.js"; diff --git a/scripts/benchmark-publish.ts b/scripts/benchmark-publish.ts index 06bc83e..224a8e9 100644 --- a/scripts/benchmark-publish.ts +++ b/scripts/benchmark-publish.ts @@ -7,7 +7,7 @@ import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; import { fileURLToPath } from "node:url"; import { c as createTar } from "tar"; -import { DEFAULT_POLICY, integrityOf, type EnterprisePolicy } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, integrityOf, type EnterprisePolicy } from "@git-agentic/sentinel-core"; import { createServer } from "../packages/proxy/src/server.js"; import { AuditStore } from "../packages/proxy/src/store.js"; import { ApprovalStore } from "../packages/proxy/src/approvals.js"; diff --git a/scripts/compat-clients.ts b/scripts/compat-clients.ts index 5f0ed67..efd920e 100644 --- a/scripts/compat-clients.ts +++ b/scripts/compat-clients.ts @@ -6,7 +6,7 @@ import type { AddressInfo } from "node:net"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { promisify } from "node:util"; -import { DEFAULT_POLICY, integrityOf, runAudit } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY, integrityOf, runAudit } from "@git-agentic/sentinel-core"; import { createServer } from "../packages/proxy/src/server.js"; import { AuditStore } from "../packages/proxy/src/store.js"; import { ApprovalStore } from "../packages/proxy/src/approvals.js"; diff --git a/scripts/demo.ts b/scripts/demo.ts index 5c121ff..417ce74 100644 --- a/scripts/demo.ts +++ b/scripts/demo.ts @@ -16,7 +16,7 @@ import { ApprovalRequestStore } from "../packages/proxy/src/approval-requests.js import { LocalFixtureUpstream } from "../packages/proxy/src/upstream.js"; import { formatReport } from "../packages/cli/src/format.js"; import type { AuditReport } from "../packages/core/src/index.js"; -import { DEFAULT_POLICY } from "@agentic-sentinel/core"; +import { DEFAULT_POLICY } from "@git-agentic/sentinel-core"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index 0c6de9e..92f9883 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -8,7 +8,7 @@ // - the proxy boots, serves the dashboard, and shuts down cleanly // - the MCP server answers an initialize handshake // - the steward fail-closes on missing config and boots with full config -// - internal @agentic-sentinel/* dependencies resolve from the packed tarballs only +// - internal @git-agentic/sentinel-* dependencies resolve from the packed tarballs only // // Requires network access (third-party deps install from the public registry). // Usage: npx tsx scripts/release-smoke.ts [--json ] [--pack-dest

] @@ -103,7 +103,7 @@ for (const ws of WORKSPACES) { const info = (JSON.parse(json) as { filename: string; size: number; entryCount: number; unpackedSize: number }[])[0]; const file = join(packDir, info.filename); const sha256 = createHash("sha256").update(readFileSync(file)).digest("hex"); - results.tarballs.push({ name: `@agentic-sentinel/${ws}`, file: info.filename, bytes: info.size, sha256, files: info.entryCount, unpacked: info.unpackedSize }); + results.tarballs.push({ name: `@git-agentic/sentinel-${ws}`, file: info.filename, bytes: info.size, sha256, files: info.entryCount, unpacked: info.unpackedSize }); console.log(` ${info.filename} ${info.size} B ${info.entryCount} files sha256:${sha256.slice(0, 16)}…`); } @@ -112,22 +112,22 @@ for (const ws of WORKSPACES) { // --------------------------------------------------------------------------- const proj = mkdtempSync(join(tmpdir(), "sentinel-smoke-")); console.log(`\n[2/5] fresh install into ${proj}`); -const fileDep = (ws: string) => `file:${join(packDir, results.tarballs.find((t) => t.name === `@agentic-sentinel/${ws}`)!.file)}`; +const fileDep = (ws: string) => `file:${join(packDir, results.tarballs.find((t) => t.name === `@git-agentic/sentinel-${ws}`)!.file)}`; const pkgJson = { name: "sentinel-release-smoke", private: true, version: "0.0.0", type: "module", - dependencies: Object.fromEntries(WORKSPACES.map((ws) => [`@agentic-sentinel/${ws}`, fileDep(ws)])), + dependencies: Object.fromEntries(WORKSPACES.map((ws) => [`@git-agentic/sentinel-${ws}`, fileDep(ws)])), // Internal deps are pinned to the (unpublished) exact prerelease version, so // transitive resolution must be forced to the local tarballs. - overrides: { "@agentic-sentinel/core": fileDep("core"), "@agentic-sentinel/proxy": fileDep("proxy"), "@agentic-sentinel/sandbox": fileDep("sandbox") }, + overrides: { "@git-agentic/sentinel-core": fileDep("core"), "@git-agentic/sentinel-proxy": fileDep("proxy"), "@git-agentic/sentinel-sandbox": fileDep("sandbox") }, }; writeFileSync(join(proj, "package.json"), JSON.stringify(pkgJson, null, 2)); run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], { cwd: proj }); console.log(" installed"); check("internal deps resolved from tarballs (not registry)", () => { const lock = JSON.parse(readFileSync(join(proj, "package-lock.json"), "utf8")) as { packages: Record }; - const bad = Object.entries(lock.packages).filter(([k, v]) => k.includes("@agentic-sentinel/") && v.resolved && !v.resolved.startsWith("file:")); + const bad = Object.entries(lock.packages).filter(([k, v]) => k.includes("@git-agentic/sentinel-") && v.resolved && !v.resolved.startsWith("file:")); if (bad.length) throw new Error(`registry-resolved: ${bad.map(([k]) => k).join(", ")}`); - return "all @agentic-sentinel/* resolved file:"; + return "all @git-agentic/sentinel-* resolved file:"; }); // --------------------------------------------------------------------------- @@ -135,22 +135,22 @@ check("internal deps resolved from tarballs (not registry)", () => { // --------------------------------------------------------------------------- console.log(`\n[3/5] imports + types`); for (const ws of WORKSPACES) { - check(`import @agentic-sentinel/${ws}`, () => { - run(process.execPath, ["-e", `import("@agentic-sentinel/${ws}").then((m)=>{ if(!m || typeof m !== "object") throw new Error("empty module") })`], { cwd: proj }); + check(`import @git-agentic/sentinel-${ws}`, () => { + run(process.execPath, ["-e", `import("@git-agentic/sentinel-${ws}").then((m)=>{ if(!m || typeof m !== "object") throw new Error("empty module") })`], { cwd: proj }); return ""; }); } check("ENGINE_VERSION matches release", () => { - const v = run(process.execPath, ["-e", `import("@agentic-sentinel/core").then((m)=>console.log(m.ENGINE_VERSION))`], { cwd: proj }).trim(); + const v = run(process.execPath, ["-e", `import("@git-agentic/sentinel-core").then((m)=>console.log(m.ENGINE_VERSION))`], { cwd: proj }).trim(); if (v !== VERSION) throw new Error(`ENGINE_VERSION=${v}, expected ${VERSION}`); return v; }); check("type declarations resolve (tsc --noEmit, NodeNext)", () => { run("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error", "-D", "typescript@^6"], { cwd: proj }); writeFileSync(join(proj, "typecheck.ts"), [ - `import { runAudit, score, DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@agentic-sentinel/core";`, - `import { createServer, NpmUpstream, type Upstream } from "@agentic-sentinel/proxy";`, - `import { createSandbox, scrubEnv } from "@agentic-sentinel/sandbox";`, + `import { runAudit, score, DEFAULT_POLICY, type AuditReport, type EnterprisePolicy } from "@git-agentic/sentinel-core";`, + `import { createServer, NpmUpstream, type Upstream } from "@git-agentic/sentinel-proxy";`, + `import { createSandbox, scrubEnv } from "@git-agentic/sentinel-sandbox";`, `const p: EnterprisePolicy = DEFAULT_POLICY;`, `void p; void runAudit; void score; void createServer; void createSandbox; void scrubEnv;`, `const u: Upstream | null = null; void u;`, diff --git a/sentinel-threat-model.md b/sentinel-threat-model.md index 2f5f3cd..23e523a 100644 --- a/sentinel-threat-model.md +++ b/sentinel-threat-model.md @@ -291,13 +291,13 @@ and stays filesystem+network confined as before. The Phase 29 `/dev/null` carve-out is unchanged (Landlock is allow-list-only and can't deny a literal under an allowed dir). `native` is advisory-only on both platforms by decision. A spawned child inherits the filesystem/network confinement on both platforms. -**Distribution note (ADR-0052):** the published `@agentic-sentinel/sandbox` npm package +**Distribution note (ADR-0052):** the published `@git-agentic/sentinel-sandbox` npm package ships the Landlock helper as *source only* — no prebuilt binary (it would be architecture-specific presented as portable) and no install-time compilation (a posture violation for a tool that guards against lifecycle scripts). A fresh npm install therefore runs the advisory exec floor on Linux, announced by a one-time notice, until the operator explicitly compiles the helper -(`node node_modules/@agentic-sentinel/sandbox/scripts/build-native.mjs`); monorepo +(`node node_modules/@git-agentic/sentinel-sandbox/scripts/build-native.mjs`); monorepo builds are unchanged. A cross-platform exec floor now exists (macOS Seatbelt, Linux Landlock where available); [issue #8](https://github.com/git-agentic/pkg-registry/issues/8)