Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
test:
name: Node ${{ matrix.node }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, macos-14]
node: [22.14.0, "24", "26"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run typecheck
- run: npm run build

contracts:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run contracts:check

package-audit:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build
- run: npm run package:audit
48 changes: 48 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Repository guide for coding agents

## Product boundary

This repository owns one public TypeScript/ESM package, `@agentcommunity/cli`, and one binary, `agentcommunity`. V1 is CLI-only and supports macOS/Linux on Node `^22.14.0 || ^24.0.0 || ^26.0.0`. Do not add a JavaScript SDK export, Windows support claim, workspace coupling to PAGE, registration, payment behavior, telemetry, an update ping, or a runtime `--base-url` without a separately approved task.

The seven public-data commands are `stats`, `member`, `verify`, `content list`, `content search`, `docs ask`, and `batch`. User-claimed authorization adds `auth login`, `auth status`, local-only `auth logout`, and current-access-token-only `auth revoke`. `register_agent` is catalog evidence only: no runtime path may call it. Link the specialist `@agentcommunity/dmv-agent` and `@agentcommunity/aid-doctor` instead of wrapping or copying them.

## Architecture

- `src/cli.ts` owns argument parsing, stdout/stderr, and stable exit-code mapping. Command modules never call `process.exit`.
- `src/http.ts` is the only production network boundary. Keep the origin fixed, redirects manual, timeouts and byte caps explicit, MIME/JSON/schema validation strict, and errors sanitized. Do not add automatic ordinary-command retries.
- `src/mcp.ts` is a narrow modern `2026-07-28` client. Runtime commands call one tool directly and never add a `tools/list` round trip.
- `src/commands/` modules orchestrate injected HTTP/MCP/filesystem/output boundaries and return typed results.
- `src/contracts.ts` validates runtime payloads and the vendored PAGE bundle. Contract scripts may fetch only for explicit maintenance; install and normal execution remain offline except for the requested command.
- `src/auth/discovery.ts` owns fail-closed path PRM/AS validation. `src/auth/device-flow.ts` owns the in-memory WorkOS `service_auth` ceremony. `src/auth/credential-store.ts` owns POSIX path, mode, ownership, locking, and atomic-write safety. Never bypass these layers or persist ceremony values.

Stable exits are: `0` success, `2` usage/local input, `3` domain-negative, `4` auth/credential safety, `5` protocol/schema/contract, `6` timeout/unavailable, `7` rate limit, and `8` mixed batch.

## Contract policy

`contracts/page/1.0.0/` must be byte-identical to the approved immutable PAGE bundle. `contracts/page.lock.json` pins version `1.0.0`, compatible range `^1.0.0`, the exact HTTPS manifest URL, and its `sha256:` hash. Never hand-edit a vendored payload or replace an immutable version. Use `npm run contracts:sync` only after PAGE publishes an approved version and the lock is intentionally reviewed. Sync must validate all bytes before writing; `npm run contracts:check` fails closed on hash, inventory, revision, fixture, or exact tool-order drift.

## Development and tests

Use test-driven development: add a focused failing fixture test, confirm the expected RED state, implement the minimum behavior, then rerun focused and full tests. Tests inject transports and must not depend on production network access.

```sh
npm ci
npm run lint
npm test
npm run typecheck
npm run build
npm run contracts:check
npm run package:audit
```

The final package audit must inspect the exact tarball allowlist and metadata, scan packed files for likely secrets, install that tarball in a clean temporary project, and run `npx --no-install agentcommunity --help`. CI covers Node 22.14, 24, and 26 on Ubuntu 24.04 and macOS.

## Security and release gates

Never log request bodies, credentials, or token-like values. The intentional verification URI/user-code progress event is the only ceremony-output exception and must occur before polling. Do not add production credentials to tests or CI. Keep package install scripts absent. Production URLs remain exact HTTPS Agent Community URLs; reject redirects and path escapes. Batch input contains no item URL, headers, credentials, or member operations.

Auth discovery always starts from an unauthenticated exact `/api` challenge and validates the path PRM, issuer, protected resource, scopes, service-auth declarations, grants, and endpoint origins before sending any secret. `auth status` is live; refresh uses only RFC 7523 JWT bearer. `auth revoke` means RFC 7009 processing of the current access token only and never delegation cancellation. PAGE members UI owns delegation management.

The credential store is POSIX-only. Require user-owned non-symlink `0700` directories and user-owned regular single-link `0600` files; reject unsafe parents, modes, owners, symlinks, hardlinks, and locks. Preserve bounded locking, conservative stale-lock checks, same-directory exclusive/no-follow temp creation, fsync-before-rename, atomic rename, directory fsync, conditional refresh/removal, and cleanup on interruption.

There is intentionally no `release.yml`. Do not publish, push, deploy, create credentials, run live auth, or add OIDC permissions without explicit owner authorization. Keep these states distinct in docs and reports: source complete, npm package published, PAGE endpoint deployed/production-capable, PAGE linked/discoverable. The current batch and agent-auth source await PAGE production deployment. A live auth smoke additionally requires an owner-authorized dedicated test account.
92 changes: 90 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,90 @@
# cli
Official command-line client for Agent Community agent interfaces
# Agent Community CLI

`@agentcommunity/cli` is the standalone command-line client for Agent Community's public agent interfaces. It provides seven read-only public-data commands plus user-claimed authorization commands and does not expose a public JavaScript SDK.

The source is complete for macOS and Linux on Node.js `^22.14.0 || ^24.0.0 || ^26.0.0`. The package is not yet published, PAGE has not yet linked it, and the branch-local batch and agent-authorization endpoints must be deployed before those commands are production-capable. Do not treat source completion as npm publication, production availability, or Agent Community discovery linkage.

## Source checkout usage

An npm install command will be added only after the package is actually published. From a source checkout:

```sh
npm ci
npm run build
node dist/cli.js --help
```

Windows is not supported in v1.

## Commands

```text
agentcommunity stats
agentcommunity member <exact-name-or-slug>
agentcommunity verify <certificate-id>
agentcommunity content list [--type docs|blog|page] [--limit 1..50] [--cursor opaque]
agentcommunity content search <query> [--type docs|blog|page] [--limit 1..50] [--cursor opaque]
agentcommunity docs ask <query> [--top-k 1..10]
agentcommunity batch <file|->
agentcommunity auth login --login-hint <email> [--scope <scope>...]
agentcommunity auth status
agentcommunity auth logout
agentcommunity auth revoke
```

Every command accepts `--json`; every remote command accepts `--timeout <ms>`. Local-only `auth logout` deliberately does not accept `--timeout`. The per-call timeout defaults to 10,000 ms and must be between 1,000 and 30,000 ms. `--json` writes exactly one final JSON value followed by LF to stdout. Human-readable output is the default and honors `NO_COLOR` (the CLI currently emits no ANSI color). Local, network, and protocol errors write one stable JSON error envelope to stderr and nothing to stdout. Semantic-negative service results still print their payload and return a nonzero status.

`auth login` has one necessary ceremony exception: it writes the verification URI and user code to stderr before polling so the user can approve the request. With `--json`, this is one `verification_required` progress object; on denial or failure, one stable error envelope follows it and stdout remains empty. On success, stdout still contains exactly one final JSON value. Human mode writes two concise instruction lines to stderr and the final result to stdout. No browser is opened automatically.

`stats` calls only modern MCP `get_community_stats`. `member` is an exact name-or-slug lookup through `lookup_member`; it never enumerates the directory or falls back to content or map search. `verify` calls only `verify_certificate`. `content list` and `content search` use `/api/v1/content`; an empty page is successful. `docs ask` posts a non-streaming request directly to `/ask`. `batch` accepts a strict JSON file or `-` for stdin, caps input at 262,144 bytes before parsing, and locally permits only `content.list` and `docs.ask` with their closed argument schemas. Unknown/member/registration operations and URL/header/credential-bearing argument escapes are rejected before network access; responses must preserve each item's ordered ID and operation.

## User-claimed authorization

`auth login` requires `--login-hint <email>` and optionally accepts either or both PAGE scopes, repeated with `--scope`: `agent.account.read` and `agent.registrations.read`. The CLI discovers authorization from the unauthenticated `/api` challenge through the exact path-scoped RFC 9728 metadata and RFC 8414 authorization-server metadata before sending any claim or bearer value. It implements the WorkOS `service_auth` claim ceremony with a 15-minute local deadline, the advertised polling interval, and cumulative five-second `slow_down` increases. The login hint is sent only in the strict identity request and is not persisted.

`auth status` is a live own-account request. When the access token has expired and the identity assertion is still valid, the CLI uses the discovered RFC 7523 JWT-bearer exchange, atomically replaces the access token only after full response validation, and then calls the own-account endpoint with exactly one Authorization header. A 401/invalid grant reports unauthenticated without destroying recoverable state; insufficient scope is distinct.

`auth logout` removes local credential state only and makes no remote request. `auth revoke` submits the current access token to the discovered RFC 7009 endpoint and removes matching local state only after HTTP 200. RFC 7009 HTTP 200 means the server accepted processing even when a token was unknown. This command does not revoke the stored identity assertion or cancel the member's delegation; delegation management remains in the PAGE members UI. Non-200 responses and timeouts preserve local state because the token may still work.

Credentials are supported only on macOS and Linux and are stored at:

- macOS: `~/Library/Application Support/agentcommunity/credentials.json`
- Linux: `${XDG_CONFIG_HOME:-~/.config}/agentcommunity/credentials.json`

The store requires a user-owned, non-symlink `0700` directory and a user-owned regular single-link `0600` file. Writers use a bounded exclusive lock, a same-directory `O_CREAT|O_EXCL|O_NOFOLLOW` `0600` temporary file, complete write and fsync, atomic rename, and directory fsync. Unsafe owners, modes, symlinks, hardlinks, path roots, locks, and interrupted replacements fail closed. Claim tokens, claim-attempt tokens, user codes, verification URIs, and login hints are never persisted.

For write-capable certificate registration use [@agentcommunity/dmv-agent](https://www.npmjs.com/package/@agentcommunity/dmv-agent). For AID diagnostics use [@agentcommunity/aid-doctor](https://www.npmjs.com/package/@agentcommunity/aid-doctor). Their behavior is intentionally not copied into this umbrella CLI.

## Exit codes

| Code | Meaning |
|---:|---|
| 0 | Success, including an empty content page, or all batch items succeeded |
| 2 | Usage/local input error or invalid certificate format |
| 3 | Member not found/ambiguous or certificate not issued |
| 4 | Authorization denied/missing/expired, insufficient scope, or credential-store safety failure |
| 5 | Remote protocol, schema, or pinned-contract mismatch |
| 6 | Timeout, network failure, upstream unavailable, or certificate verifier unavailable |
| 7 | Rate limited; a valid bounded `Retry-After` value is included when available |
| 8 | Batch transport succeeded but at least one ordered item failed |

## Privacy and network behavior

There is no telemetry, analytics identifier, update ping, request-body logging, credential logging, or hidden network request. Production requests are fixed to `https://agentcommunity.org`; there is no runtime `--base-url`. Redirects are rejected, response sizes are capped, JSON MIME and schemas are validated, and ordinary commands are never retried automatically. Auth polling alone repeats according to the discovered ceremony contract and never resets its local deadline after a network interruption. Token-like values are redacted from error serialization; access tokens travel only in the Authorization header or the exact RFC 7009 form, and assertions/claim tokens travel only in their standard discovered endpoint forms.

Runtime commands use the committed PAGE contract bundle `1.0.0`, whose manifest SHA-256 is `b1f10b6288e436ccdca282b88a9a9115fcc0f6716f90731aab1455175b535595`. Contract sync is an explicit maintainer operation and never runs during install or normal execution.

## Contributing

Read [AGENTS.md](./AGENTS.md) before changing source. The deterministic quality gate is:

```sh
npm run lint
npm test
npm run typecheck
npm run build
npm run contracts:check
npm run package:audit
```

Publishing, release automation, production deployment, and PAGE linking require separate owner authorization and live verification. PAGE agent authorization is not live as of this source change. Do not run a real login, status, or revoke until PAGE auth is deployed and an owner explicitly authorizes a dedicated test account.
11 changes: 11 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Security policy

Report suspected vulnerabilities privately to `security@agentcommunity.org`. Do not open a public issue containing credentials, tokens, personal data, or an exploitable proof of concept.

The supported source targets are the maintained Node.js versions declared in `package.json` on macOS and Linux. No npm release has been published yet, so there is no released version support table.

The CLI sends only explicitly requested public-data or user-claimed authorization operations to fixed `https://agentcommunity.org` endpoints. It has no telemetry, update checks, install-time network script, silent browser opening, or runtime base-URL override. Redirects are rejected, discovery and response contracts fail closed, and network errors are sanitized.

User authorization is limited to read-only own-account scopes. The CLI validates path-scoped protected-resource and authorization-server metadata before sending any bearer, assertion, or claim value. Access tokens are used only in Authorization headers and the RFC 7009 revocation form; assertions and claim tokens are sent only in the exact discovered standard forms. Claim tokens, claim-attempt tokens, verification URIs, user codes, and login hints are never persisted. `auth revoke` processes only the current access token and does not cancel a member delegation.

On macOS/Linux, credential storage requires user-owned non-symlink `0700` directories and user-owned regular single-link `0600` files. Writes use bounded exclusive locking, exclusive/no-follow same-directory temporary files, fsync, atomic rename, directory fsync, and conditional replacement/removal. Unsafe paths, ownership, permissions, links, locks, or interrupted writes fail closed. Windows is not supported.
6 changes: 6 additions & 0 deletions contracts/page.lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"bundle_version": "1.0.0",
"compatible_range": "^1.0.0",
"manifest_url": "https://agentcommunity.org/.well-known/agentcommunity-contracts/1.0.0/manifest.json",
"manifest_sha256": "sha256:b1f10b6288e436ccdca282b88a9a9115fcc0f6716f90731aab1455175b535595"
}
Loading
Loading