Skip to content

Commit 8e45c29

Browse files
committed
feat: enhance package manifest and migration documentation, add install mode and permissions model details
1 parent f439614 commit 8e45c29

6 files changed

Lines changed: 464 additions & 15 deletions

File tree

docs/spec/02-manifest.md

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,18 @@ The manifest is the **single required file**. It identifies the package and decl
7474

7575
// === PERMISSIONS (optional) ===
7676
"permissions": { // Requested agent capabilities
77-
"fs": ["read", "write"], // Filesystem access scope
78-
"network": ["api.github.com"], // Allowed network hosts
79-
"shell": false // Allow arbitrary shell execution
77+
"fs": { // Filesystem access — path-scoped
78+
"read": ["src/**", "docs/**"], // Glob patterns the package may read
79+
"write": ["output/**", ".cache/**"] // Glob patterns the package may write/delete
80+
},
81+
"network": { // Network access
82+
"hosts": ["api.github.com", "*.npmjs.org"], // Exact host or wildcard subdomain
83+
"schemes": ["https"] // Allowed URI schemes (https | http | wss)
84+
},
85+
"shell": { // Shell execution
86+
"allow": true, // false = no shell; true = allow listed binaries
87+
"binaries": ["git", "npm", "python3"] // Explicit allow-list (ignored when allow=false)
88+
}
8089
},
8190

8291
// === QUALITY (optional) ===
@@ -104,7 +113,17 @@ The manifest is the **single required file**. It identifies the package and decl
104113
"hooks": "./hooks/hooks.json", // Default: ./hooks/hooks.json
105114
"mcp": "./mcp/servers.json", // Default: ./mcp/servers.json
106115

116+
// === INSTALL MODE (optional, for adoption transitioning) ===
117+
"installMode": { // Default: "uaaps" for all platforms
118+
"default": "uaaps", // "uaaps" | "plugin"
119+
"claude-code": "plugin", // Per-platform override
120+
"cursor": "uaaps"
121+
},
122+
107123
// === VENDOR EXTENSIONS (optional) ===
124+
// Keys MUST be "x-<vendor-id>" where vendor-id matches [a-z0-9-], max 32 chars.
125+
// Values MUST be JSON objects (not scalars or arrays).
126+
// Tools MUST silently ignore unrecognised x-* keys.
108127
"x-claude": {
109128
"marketplace": "anthropics/skills"
110129
},
@@ -135,7 +154,7 @@ dependencies:
135154
code-review: "^1.0.0"
136155

137156
x-claude:
138-
marketplace: anthropics/skills
157+
marketplace: anthropics/skills # x-<vendor-id>, value MUST be an object
139158

140159
x-cursor:
141160
category: Developer Tools
@@ -146,6 +165,29 @@ x-cursor:
146165
- CLI tools (`aam install`, etc.) generate `package.agent.json` as the canonical output.
147166
- Lock files (`package.agent.lock`) are always JSON.
148167

168+
### Vendor Extensions
169+
170+
Vendor extensions allow platforms and tools to attach platform-specific metadata to a package manifest without conflicting with the core schema.
171+
172+
#### Naming Rules
173+
174+
- Keys MUST use the prefix `x-<vendor-id>`, where `vendor-id` is a lowercase alphanumeric slug matching `[a-z0-9-]+`, maximum 32 characters (e.g. `x-claude`, `x-cursor`, `x-copilot`).
175+
- The `vendor-id` SHOULD match either a registered platform identifier from the [compatibility matrix](09-compatibility.md) or the package's own scope identifier (e.g. `x-myorg` for `@myorg/` scoped packages).
176+
- Extension values MUST be JSON objects. Scalar values (strings, booleans, numbers) and arrays MUST NOT be used as the top-level value of an `x-*` key.
177+
- Packages SHOULD NOT declare more than **5** `x-*` keys. `aam validate` MUST warn when more than 5 are present (see §16 Validation).
178+
179+
#### Interoperability Rules
180+
181+
- Tools and runtimes MUST silently ignore unrecognised `x-*` keys. Tools MUST NOT error or refuse to install a package solely because of an unknown `x-*` key.
182+
- Registry indexing: only `x-<known-platform>` keys (those matching a registered platform) are indexed and searchable. Unknown `x-*` keys are stored but not indexed.
183+
- Registry validation SHOULD produce a `WARN`-level diagnostic for `x-*` keys that do not match any registered platform identifier, to alert the author that the key will not be indexed.
184+
185+
#### Conflict Avoidance
186+
187+
- Two packages MUST NOT declare the same `x-*` key with structurally incompatible schemas. The registry MAY enforce a canonical JSON Schema per registered `x-<vendor>` key.
188+
- Authors MUST NOT use another vendor's registered `x-*` key to override or shadow that vendor's metadata.
189+
- Private extensions for in-house tooling SHOULD use the package owner's scope as the vendor-id (e.g. `x-myorg`) to avoid collisions with future registered platforms.
190+
149191
### Vendor Mapping
150192

151193
| Manifest Field | Claude Code (`plugin.json`) | Cursor (`.cursor-plugin/plugin.json`) |

docs/spec/10-migration.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,75 @@ alwaysApply: false alwaysApply: false
5858
```
5959

6060
The formats are functionally identical. Only the file extension changes.
61+
62+
---
63+
64+
## 11.1 Install Mode — Smooth Adoption Before Full Vendor Implementation
65+
66+
The `installMode` field in `package.agent.json` allows a package author to declare how the package SHOULD be deployed on platforms that have not yet natively implemented the UAAPS standard. This enables smooth adoption: one package can target both UAAPS-native environments and platforms still using their own plugin system.
67+
68+
### Mode Values
69+
70+
| Value | Install target | When to use |
71+
|-------|---------------|-------------|
72+
| `uaaps` (default) | `.agent-packages/` — full UAAPS layout | Platform supports UAAPS natively |
73+
| `plugin` | Vendor-native location (see table below) | Platform uses its own plugin system |
74+
75+
### `installMode` in `package.agent.json`
76+
77+
```jsonc
78+
{
79+
"name": "@myorg/code-review",
80+
"version": "1.0.0",
81+
82+
// Omit entirely to use "uaaps" for all platforms (recommended default)
83+
"installMode": {
84+
"default": "uaaps", // Fallback for any platform not listed
85+
"claude-code": "plugin", // Deploy as native Claude Code plugin
86+
"cursor": "uaaps" // Deploy via UAAPS on Cursor
87+
}
88+
}
89+
```
90+
91+
A scalar string shorthand MAY be used when the same mode applies to all platforms:
92+
93+
```jsonc
94+
"installMode": "plugin" // plugin mode on every platform
95+
```
96+
97+
### Plugin Mode — Vendor-Native Deploy Targets
98+
99+
When `installMode` resolves to `"plugin"` for a given platform, the `aam` CLI translates and deploys artifacts to the platform's native location using the same mapping logic as `aam pkg build --target <platform>` (see §12.4):
100+
101+
| Platform | `plugin` mode install target |
102+
|----------|-----------------------------|
103+
| `claude-code` | `.claude/` (skills, commands, agents, hooks) |
104+
| `cursor` | `.cursor/rules/` (rules as `.mdc`), `.cursor/skills/` |
105+
| `copilot` | `.github/instructions/`, `.github/agents/`, `.github/skills/` |
106+
| `codex` | `AGENTS.md` composite inject |
107+
108+
### CLI Override
109+
110+
Users MAY override the manifest declaration at install time:
111+
112+
```bash
113+
# Force plugin mode regardless of manifest
114+
aam install @myorg/code-review --install-mode plugin
115+
116+
# Force uaaps mode regardless of manifest
117+
aam install @myorg/code-review --install-mode uaaps
118+
119+
# Target a specific platform's plugin layout
120+
aam install @myorg/code-review --install-mode plugin --platform claude-code
121+
```
122+
123+
### Deprecation Path
124+
125+
Once a platform vendor implements UAAPS natively, `"plugin"` mode for that platform becomes a no-op — the `aam` CLI SHOULD silently promote it to `"uaaps"` and emit an informational message:
126+
127+
```
128+
⚠ installMode "plugin" for claude-code is ignored — platform supports UAAPS natively.
129+
Update package.agent.json to remove the per-platform override.
130+
```
131+
132+
Package authors SHOULD remove per-platform `plugin` overrides once the target platform is listed as UAAPS-native in the compatibility matrix (§10).

docs/spec/11-packaging.md

Lines changed: 213 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,235 @@
22

33
### UAAPS Registry
44

5-
Packages are published to and installed from a **UAAPS registry** — an HTTP server implementing the UAAPS registry protocol. The official public registry is `registry.agentpkg.io`; organizations can self-host a private registry.
5+
UAAPS supports two registry types that share the same package format (`.aam` archives) but differ in transport:
6+
7+
| Type | When to use |
8+
|------|-------------|
9+
| **Local filesystem** | Offline use, air-gapped environments, CI mirrors, monorepos |
10+
| **HTTP remote** | Public registry, private org registry, hosted SaaS |
11+
12+
The `aam` CLI auto-detects the registry type from the URL scheme:
613

714
```bash
8-
# Install from the default registry
9-
aam install @myorg/code-review
15+
# HTTP remote registry
16+
aam install @myorg/code-review --registry https://aamregistry.io
1017

11-
# Install from a private registry
12-
aam install @myorg/code-review --registry https://pkg.myorg.internal/aam
18+
# Local filesystem registry
19+
aam install @myorg/code-review --registry file:///opt/aam-registry
1320

14-
# Publish to a registry
15-
aam pkg publish --registry https://pkg.myorg.internal/aam
21+
# Default registry (HTTP, configured in ~/.aam/config.yaml)
22+
aam install @myorg/code-review
1623
```
1724

1825
Registry configuration is managed in `~/.aam/config.yaml` or `.aam/config.yaml`:
1926

2027
```yaml
2128
registries:
22-
default: https://registry.agentpkg.io
29+
default: https://aamregistry.io
2330
sources:
24-
- name: myorg
31+
- name: myorg-remote
2532
url: https://pkg.myorg.internal/aam
33+
auth: token # see §12.6 for auth types
34+
- name: myorg-local
35+
url: file:///opt/aam-registry
2636
```
2737
2838
> Other distribution channels (Git marketplace, npm bridge, direct install, project-bundled) are supported by the `aam` CLI — see `aam_cli_new.md`.
2939

40+
### 12.5 Local Filesystem Registry
41+
42+
A local filesystem registry is a **directory tree** on disk following a defined layout. No server process is required. It is suitable for offline installs, CI artifact mirrors, and air-gapped enterprise environments.
43+
44+
#### Directory Layout
45+
46+
```
47+
<registry-root>/
48+
├── index.json # Full package index (all packages + versions)
49+
├── packages/
50+
│ ├── code-review/ # Unscoped package
51+
│ │ ├── meta.json # Package metadata (all versions)
52+
│ │ └── versions/
53+
│ │ ├── 1.0.0.aam
54+
│ │ ├── 1.0.0.aam.sha256 # Detached SHA-256 checksum
55+
│ │ ├── 1.1.0.aam
56+
│ │ └── 1.1.0.aam.sha256
57+
│ └── myorg--code-review/ # Scoped package (@myorg/code-review)
58+
│ ├── meta.json
59+
│ └── versions/
60+
│ ├── 2.0.0.aam
61+
│ └── 2.0.0.aam.sha256
62+
└── dist-tags.json # Global dist-tag → version map
63+
```
64+
65+
#### `index.json`
66+
67+
A flat list of all packages in the registry. Implementations MUST regenerate this file after every publish or unpublish operation.
68+
69+
```json
70+
{
71+
"formatVersion": 1,
72+
"updatedAt": "2026-02-22T14:00:00Z",
73+
"packages": [
74+
{ "name": "code-review", "latest": "1.1.0", "versions": ["1.0.0", "1.1.0"] },
75+
{ "name": "@myorg/code-review", "latest": "2.0.0", "versions": ["2.0.0"] }
76+
]
77+
}
78+
```
79+
80+
#### `packages/<name>/meta.json`
81+
82+
Per-package metadata covering all published versions.
83+
84+
```json
85+
{
86+
"name": "@myorg/code-review",
87+
"versions": {
88+
"2.0.0": {
89+
"version": "2.0.0",
90+
"description": "Code review skills for myorg",
91+
"author": "myorg",
92+
"publishedAt": "2026-02-20T10:00:00Z",
93+
"integrity": "sha256-abc123...",
94+
"tarball": "versions/2.0.0.aam"
95+
}
96+
},
97+
"dist-tags": {
98+
"latest": "2.0.0",
99+
"stable": "2.0.0"
100+
}
101+
}
102+
```
103+
104+
#### `dist-tags.json`
105+
106+
Registry-wide dist-tag snapshot for fast tag resolution without reading every `meta.json`.
107+
108+
```json
109+
{
110+
"code-review": { "latest": "1.1.0", "stable": "1.0.0" },
111+
"@myorg/code-review": { "latest": "2.0.0" }
112+
}
113+
```
114+
115+
#### Filesystem Registry Rules
116+
117+
| Rule | Requirement |
118+
|------|-------------|
119+
| Package directory name MUST use the `scope--name` mapping (§12.2) | MUST |
120+
| Every `.aam` file MUST have a sibling `.aam.sha256` file | MUST |
121+
| `index.json` MUST be regenerated atomically after each mutation | MUST |
122+
| Symlinks outside the registry root are forbidden | MUST NOT |
123+
| The registry root MAY be read-only (install-only mirror) | MAY |
124+
125+
#### CLI Commands for Local Registries
126+
127+
```bash
128+
# Initialise a new local registry
129+
aam registry init file:///opt/aam-registry
130+
131+
# Publish a package to a local registry
132+
aam pkg publish --registry file:///opt/aam-registry
133+
134+
# Rebuild index.json after manual archive placement
135+
aam registry reindex file:///opt/aam-registry
136+
137+
# List all packages in a local registry
138+
aam registry ls file:///opt/aam-registry
139+
```
140+
141+
---
142+
143+
### 12.6 HTTP Registry Protocol
144+
145+
> **Status: Skeleton** — endpoint signatures and auth model are defined below. Full request/response schemas, pagination rules, rate-limit headers, and error codes will be detailed in a dedicated Registry Protocol document in a future spec revision.
146+
147+
An HTTP registry is an HTTPS server implementing the UAAPS Registry Protocol. The official public registry is `https://aamregistry.io`. Organizations MAY self-host a private registry.
148+
149+
#### Base URL
150+
151+
All endpoints are relative to the registry base URL. Implementations MUST serve the API over HTTPS. Plain HTTP MUST NOT be used for registries handling private packages or authentication tokens.
152+
153+
#### Endpoint Index
154+
155+
> **TODO**: This is a preliminary endpoint list and is not final. Additional endpoints (e.g. search, package transfer, org management, audit log) will be added in the Registry Protocol document.
156+
157+
| Method | Path | Purpose | Auth required |
158+
|--------|------|---------|--------------|
159+
| `GET` | `/` | Registry metadata & capabilities | No |
160+
| `GET` | `/packages` | List all packages (paginated) | No (public) / Yes (private) |
161+
| `GET` | `/packages/:name` | Package metadata (all versions) | No (public) / Yes (private) |
162+
| `GET` | `/packages/:name/:version` | Single version metadata | No (public) / Yes (private) |
163+
| `GET` | `/packages/:name/:version/tarball` | Download `.aam` archive | No (public) / Yes (private) |
164+
| `GET` | `/packages/:name/:version/signature` | Fetch signature bundle | No |
165+
| `GET` | `/packages/:name/dist-tags` | List dist-tags for package | No |
166+
| `PUT` | `/packages/:name/dist-tags/:tag` | Set a dist-tag | Yes |
167+
| `DELETE` | `/packages/:name/dist-tags/:tag` | Remove a dist-tag | Yes |
168+
| `POST` | `/packages` | Publish a new package version | Yes |
169+
| `DELETE` | `/packages/:name/:version` | Unpublish a version | Yes |
170+
| `GET` | `/approvals` | List pending approval requests | Yes |
171+
| `POST` | `/approvals/:id/approve` | Approve a publish request | Yes |
172+
| `POST` | `/approvals/:id/reject` | Reject a publish request | Yes |
173+
174+
#### Authentication
175+
176+
HTTP registries MAY require authentication. The `aam` CLI supports the following auth types, configured per registry in `~/.aam/config.yaml`:
177+
178+
| Auth type | Config value | Transport |
179+
|-----------|-------------|-----------|
180+
| No auth (public) | `auth: none` ||
181+
| Static token | `auth: token` | `Authorization: Bearer <token>` header |
182+
| OIDC / Sigstore keyless | `auth: oidc` | Short-lived token via OIDC provider |
183+
| Basic (legacy, not recommended) | `auth: basic` | `Authorization: Basic <base64>` header |
184+
185+
```yaml
186+
# ~/.aam/config.yaml
187+
registries:
188+
sources:
189+
- name: myorg
190+
url: https://pkg.myorg.internal/aam
191+
auth: token
192+
token: "${MYORG_AAM_TOKEN}" # resolved from environment variable
193+
```
194+
195+
Tokens MUST be stored in environment variables or a secrets manager. Tokens MUST NOT be committed to version control. The `aam login` command handles interactive token acquisition and secure local storage.
196+
197+
```bash
198+
aam login --registry https://pkg.myorg.internal/aam # interactive login
199+
aam logout --registry https://pkg.myorg.internal/aam # remove stored credential
200+
aam whoami --registry https://pkg.myorg.internal/aam # show current identity
201+
```
202+
203+
#### Error Response Format
204+
205+
All error responses MUST use `application/json` with this structure:
206+
207+
```json
208+
{
209+
"error": {
210+
"code": "PACKAGE_NOT_FOUND",
211+
"message": "Package @myorg/code-review@3.0.0 does not exist.",
212+
"docs": "https://aamregistry.io/errors/PACKAGE_NOT_FOUND"
213+
}
214+
}
215+
```
216+
217+
#### Standard Status Codes
218+
219+
| Code | Meaning |
220+
|------|---------|
221+
| `200` | Success |
222+
| `201` | Published successfully |
223+
| `400` | Malformed request |
224+
| `401` | Authentication required |
225+
| `403` | Insufficient permissions |
226+
| `404` | Package or version not found |
227+
| `409` | Version already exists (publish conflict) |
228+
| `422` | Validation failed (manifest schema error) |
229+
| `429` | Rate limit exceeded |
230+
| `503` | Registry temporarily unavailable |
231+
232+
> Full pagination headers, rate-limit headers, conditional request support (`ETag`, `If-None-Match`), and approval workflow request/response bodies will be defined in the Registry Protocol document.
233+
30234
### 12.1 Archive Distribution Format
31235

32236
Packages are distributed as **`.aam` archives** (gzipped tar), providing a binary-safe, single-file distribution unit.

0 commit comments

Comments
 (0)