@intentic/registry-scan 1.310.0 → 1.311.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +23 -76
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -1,85 +1,32 @@
1
- # @intentic/registry-scan
1
+ # registry-scan
2
2
 
3
- The nightly job behind the [extension registry](seed/README.md). Published to npm because it runs from a
4
- GitHub Actions inside a public repository this monorepo does not contain. The workflows invoke an exact npm
5
- version from the `REGISTRY_SCAN_VERSION` repository variable; a moving package tag is not allowed inside the
6
- admission boundary.
3
+ The CLI behind the extension registry: it finds topic-tagged extension repos, refreshes their facts, proposes listings, and prepares the security audit that admits new code.
7
4
 
8
- The file format it reads and writes lives in [`@intentic/registry`](../../_shared/registry), which the daemon
9
- and the site's gallery use too, so all three agree by construction rather than by three copies of a zod
10
- schema staying in step.
11
-
12
- ## What it does, and what it refuses to do
13
-
14
- Scanning GitHub for a topic is **discovery**. Merging a pull request is the **decision**. Keeping those apart
15
- is the entire design: a topic is a public namespace anybody can join, so a job that listed what it found
16
- would publish the first malicious repository to tag itself: and the alternative, a submission form on the
17
- site, is a login, a spam queue and an admin panel standing in for a git commit.
18
-
19
- So each run:
20
-
21
- 1. Searches `topic:intentic-extension`.
22
- 2. Refreshes stars and last-push for **already-listed** entries into `registry.generated.json`, including the
23
- listings the topic search never returned (a listing that arrived by pull request has no obligation to
24
- carry the topic, and dropping its stars for that would rank it below newcomers for no reason).
25
- 3. For each **unlisted** repo, resolves the default branch to a commit first, then reads the manifest and bundle
26
- only at that sha. It proposes a complete candidate `marketplace.json` only when both parse/load there.
27
- 4. Emits warnings for everything it skipped, into the job summary.
28
-
29
- It never lists, delists, or changes a trust level. A repository that went briefly private should come back to
30
- its listing, not to a deletion.
31
-
32
- Those are proposal checks, not admission. The protected `extension admission` workflow runs on each executable
33
- source/review change and accepts one executable subject per pull request. `audit` refuses unpinned, unsafe-host,
34
- or escaping-path targets. A disposable no-secrets job fetches the exact source and runs Trivy's
35
- dependency, secret, and misconfiguration scanners. Only then does the intentic agent gate receive an adversarial
36
- brief covering browser globals/egress, server/process credentials, agent hooks and MCP, bin shadowing,
37
- image/environment fragments, dependencies, binaries and source-versus-dist. It treats repository content as
38
- untrusted and forbids executing author code. Either automated check failing, blocking, or remaining unjudged
39
- fails admission.
40
-
41
- A pass runs `attest`, which records both run identities against the exact repository, sha and subdirectory. That
42
- push changes the PR head, so branch protection evaluates both checks again on the attested commit. Unchanged
43
- metadata may reuse evidence for the same immutable subject; a changed repository, sha or path, unblocking, or an
44
- edit to the record reruns admission. After a policy or scanner upgrade, untouched stale rows remain disabled by
45
- the official registry resolver; touching one schedules just that source, so the catalogue can be refreshed one
46
- pull request at a time. The privileged jobs fetch only the candidate marketplace JSON; exact source is checked
47
- out solely on the disposable deterministic runner and is never executed.
48
-
49
- Identity is also enforced mechanically. The listing key is `publisher.name` read from the manifest:
50
- [`extensionIdOf`](../../_shared/extension-manifest/src/manifest.ts): so a repository that copies somebody else's
51
- manifest collides with their existing listing and is refused here rather than arriving as a pull request that
52
- looks legitimate.
5
+ ```mermaid
6
+ flowchart LR
7
+ wf["intentic/registry<br/>GitHub Actions"] -->|"npm exec"| cli(["registry-scan"])
8
+ cli -->|"scan"| gh["GitHub API<br/>topic intentic-extension"]
9
+ cli -->|"scan"| out["registry.generated.json<br/>.scan/proposals/"]
10
+ cli -->|"audit"| req["security request<br/>for the intentic gate"]
11
+ cli -->|"attest"| stamp["review bound to<br/>the candidate sha"]
12
+ ```
53
13
 
54
- ## Layout
14
+ - Runs in the registry repository's workflows, which [seed/](seed) holds, pinned to one exact published version. Nothing in this repo runs it.
15
+ - `scan` reads `.claude-plugin/marketplace.json`, searches GitHub for the `intentic-extension` topic and reads each repo's root `intentic-extension.json` at an exact commit. It rewrites the facts file in place and leaves one directory per new extension under `.scan/proposals/`, holding a candidate `marketplace.json` and the pull request's text, so the workflow only moves whole files.
16
+ - Nothing merges automatically. A proposal enters as `trust: "listed"`, `verified` is a separate human edit, and delisting stays manual. Gone, archived or broken listings become warnings for a maintainer.
17
+ - `audit` validates a registry diff and lists every changed executable source; `attest` records a passing gate run against those exact shas. Registry content is untrusted data, and no author code runs anywhere in the chain.
18
+ - `github.ts` sits behind an interface, so the decision logic in `scan.ts` is tested with no network or token.
55
19
 
56
- | Path | What it is |
57
- | --- | --- |
58
- | [src/scan.ts](src/scan.ts) | The decision logic, pure and fully unit-tested against a fake reader. |
59
- | [src/audit.ts](src/audit.ts) | Diff-to-check policy and source-bound attestation. |
60
- | [src/github.ts](src/github.ts) | The four REST reads, behind an interface so the above needs no network. |
61
- | [src/cli.ts](src/cli.ts) | The IO: read the checkout, write the facts file and the proposal directories. |
62
- | [seed/](seed) | What the registry repository itself contains: the curated file, the author-facing README, and the workflow that calls this. |
20
+ ## Key files
63
21
 
64
- `seed/` is a starting point, not a synced copy: push it once to create the registry repository, then it lives
65
- its own life over there. The one coupling that matters is the workflow's `npx` line, which is why this
66
- package is published.
22
+ - [src/cli.ts](src/cli.ts) — the `scan`, `audit` and `attest` commands and their inputs.
23
+ - [src/scan.ts](src/scan.ts) — discovery, fact refresh and listing proposals.
24
+ - [src/audit.ts](src/audit.ts) — admission problems, audit targets and the attestation.
25
+ - [src/outputs.ts](src/outputs.ts) — everything the scan writes for the workflow to pick up.
67
26
 
68
- ## Running it against a checkout
27
+ ## Commands
69
28
 
70
29
  ```sh
71
- GITHUB_TOKEN=… REGISTRY_DIR=/path/to/registry-checkout node dist/cli.js
72
- node dist/cli.js audit --base /path/to/base.json --candidate /path/to/candidate.json
73
- node dist/cli.js attest --base /path/to/base.json --candidate /path/to/candidate.json --run-id GATE_RUN --scan-run-id WORKFLOW_RUN
30
+ pnpm --filter @intentic/registry-scan test
31
+ GITHUB_TOKEN=… REGISTRY_DIR=<registry checkout> pnpm --filter @intentic/registry-scan scan # after build
74
32
  ```
75
-
76
- `SCANNED_AT` overrides the timestamp so a re-run against a fixed input produces a fixed output. A token is
77
- required: the search and contents endpoints are rate-limited to approximately nothing without one.
78
-
79
- ## Key files
80
-
81
- - [src/scan.ts](src/scan.ts): finding extensions and resolving each to a sha.
82
- - [src/audit.ts](src/audit.ts): identifying executable changes and preparing the intentic gate.
83
- - [src/github.ts](src/github.ts): the API half.
84
- - [src/outputs.ts](src/outputs.ts): what the job writes.
85
- - [src/cli.ts](src/cli.ts): the entry point the nightly job runs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentic/registry-scan",
3
- "version": "1.310.0",
3
+ "version": "1.311.0",
4
4
  "description": "The nightly scan behind the extension registry, finds topic-tagged repos, refreshes upstream facts, and proposes listings as pull requests",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "registry": "https://registry.npmjs.org/"
21
21
  },
22
22
  "dependencies": {
23
- "@intentic/extension-manifest": "1.310.0",
24
- "@intentic/registry": "1.310.0",
23
+ "@intentic/extension-manifest": "1.311.0",
24
+ "@intentic/registry": "1.311.0",
25
25
  "zod": "4.5.4"
26
26
  },
27
27
  "devDependencies": {