@awebai/pi 0.1.8 → 0.1.10
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.
- package/package.json +2 -2
- package/skills/aweb-coordination/SKILL.md +125 -70
- package/skills/aweb-identity/SKILL.md +172 -0
- package/skills/aweb-team-membership/SKILL.md +137 -129
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awebai/pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Aweb for Pi: real-time channel awakenings, aw CLI onboarding, and aweb skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"channel"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"sync-skills": "rm -rf skills && mkdir -p skills && cp -R ../skills/aweb-coordination ../skills/aweb-messaging ../skills/aweb-team-membership ../skills/aweb-bootstrap skills/",
|
|
21
|
+
"sync-skills": "rm -rf skills && mkdir -p skills && cp -R ../skills/aweb-coordination ../skills/aweb-messaging ../skills/aweb-team-membership ../skills/aweb-bootstrap ../skills/aweb-identity skills/",
|
|
22
22
|
"build": "npm run sync-skills && rm -rf dist && tsc -p tsconfig.json --noEmit && npx esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:@awebai/aw",
|
|
23
23
|
"test:package": "node scripts/check-package-dist.mjs",
|
|
24
24
|
"prepack": "npm run build && npm run test:package",
|
|
@@ -1,123 +1,178 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: aweb-coordination
|
|
3
|
-
description: This skill should be used when
|
|
3
|
+
description: This skill should be used when working in an aweb-coordinated team — checking what teammates are doing, discovering and sharing tasks, claiming work, taking manual locks on contested resources, reading or setting shared team roles and instructions, creating sibling worktrees with `aw workspace add-worktree`, and deciding whether to record coordination in shared aweb state versus private notes.
|
|
4
4
|
allowed-tools: "Bash(aw *)"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# aweb Coordination
|
|
8
8
|
|
|
9
|
-
Use this skill
|
|
9
|
+
Use this skill when sharing work with a team of agents through aweb. Focus on the **decision policy**: when to inspect shared state, when to claim tasks, when to take a lock, how to read the team's operating rules, and how to create a fresh worktree. Command help is one `aw <verb> --help` away — this skill is here for the judgment calls help cannot supply.
|
|
10
10
|
|
|
11
|
-
For mail/chat
|
|
11
|
+
For mail/chat response policy, load `aweb-messaging`. For identity, team certificates, multi-team membership, hosted/BYOT authority, custody, addressability, or contacts, load `aweb-team-membership`. For creating a new aweb team from a template, load `aweb-bootstrap`.
|
|
12
|
+
|
|
13
|
+
## What aweb gives the team
|
|
14
|
+
|
|
15
|
+
A short map of the primitives this skill assumes are available. Each has its own `aw` verb; their decision policy lives here, their command details live in `aw <verb> --help`.
|
|
16
|
+
|
|
17
|
+
- **Tasks** (`aw task`) — the durable record of work items: create, list, show, update, comment, close.
|
|
18
|
+
- **Work discovery** (`aw work`) — the dashboard-style view over those tasks combined with current claim state: `ready` (unclaimed), `active` (in-progress across the team), `blocked`.
|
|
19
|
+
- **Mail** (`aw mail`) — async, signed, durable; the default for handoffs and review requests. Details in `aweb-messaging`.
|
|
20
|
+
- **Chat** (`aw chat`) — sync, signed, waits on a response. Details in `aweb-messaging`.
|
|
21
|
+
- **Locks** (`aw lock`) — explicit, manual coordination primitives for contested resources. Not automatic.
|
|
22
|
+
- **Presence** — `aw workspace status` shows who is online; `aw heartbeat` sends an explicit presence beat.
|
|
23
|
+
- **Roles** (`aw roles`, `aw role-name`) — a versioned bundle of role definitions plus the current workspace's role assignment.
|
|
24
|
+
- **Instructions** (`aw instructions`) — a versioned shared team-instructions document every agent reads on wake-up.
|
|
25
|
+
- **Worktrees** (`aw workspace add-worktree`) — create a sibling git worktree wired up as its own coordination workspace.
|
|
12
26
|
|
|
13
27
|
## Start-of-session loop
|
|
14
28
|
|
|
15
|
-
Run
|
|
29
|
+
Run these before claiming new work. Order is deliberate.
|
|
16
30
|
|
|
17
31
|
```bash
|
|
18
|
-
aw workspace status
|
|
19
|
-
aw mail inbox
|
|
20
|
-
aw chat pending
|
|
21
|
-
aw work ready
|
|
32
|
+
aw workspace status # who is online, active team, identity, claims, locks
|
|
33
|
+
aw mail inbox # async handoffs, reviews, blockers — process first
|
|
34
|
+
aw chat pending # someone may be blocked waiting on you
|
|
35
|
+
aw work ready # only after the above; pick the smallest actionable item
|
|
22
36
|
```
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
If `aw workspace status` reports the directory is not bound to a team (no `.aw/workspace.yaml`, no certificate, etc.), stop and load `aweb-team-membership` before doing coordination work.
|
|
39
|
+
|
|
40
|
+
## Seeing what teammates are doing
|
|
41
|
+
|
|
42
|
+
Before you claim work or send a message, get the team's current state. These are read-only and cheap:
|
|
43
|
+
|
|
44
|
+
- `aw work active` — every task currently claimed across the team, who has it, and the status. The first place to look when wondering "is someone already on this?"
|
|
45
|
+
- `aw work ready` — unclaimed tasks the team would benefit from picking up.
|
|
46
|
+
- `aw work blocked` — tasks paused on a dependency or external answer.
|
|
47
|
+
- `aw task list` — full task index with filters (status, assignee, label).
|
|
48
|
+
- `aw task show <task-id>` — full task including comments, dependencies, and history.
|
|
49
|
+
- `aw workspace status` — presence for the active team (who is online right now).
|
|
50
|
+
- `aw mail inbox` and `aw chat history <alias>` — recent messages, including what teammates have been talking about.
|
|
51
|
+
|
|
52
|
+
Some teammates may be members of more than one team. The commands above only show the active team's state. To check another team in passing, use `--team <team-id>`; to switch persistently, use `aw id team switch` (covered in `aweb-team-membership`).
|
|
53
|
+
|
|
54
|
+
## Contacting teammates
|
|
25
55
|
|
|
26
|
-
|
|
27
|
-
2. **Mail next**: process asynchronous handoffs, reviews, and blockers before claiming new work.
|
|
28
|
-
3. **Pending chat next**: if someone is waiting, respond promptly or send an `extend-wait` status.
|
|
29
|
-
4. **Ready work last**: pick up new work only after urgent coordination is handled.
|
|
56
|
+
Mail and chat are the contact surface. The policy lives in `aweb-messaging`, but in a coordination context the defaults are:
|
|
30
57
|
|
|
31
|
-
|
|
58
|
+
- **Mail** (`aw mail send --to <alias> --body ...`) — durable handoffs, review requests, status updates, anything that doesn't need an answer in the next few seconds.
|
|
59
|
+
- **Chat** (`aw chat send-and-wait <alias> "..."`) — when the teammate is online and you are blocked on their answer. Sets a wait state the harness surfaces to them.
|
|
60
|
+
- For cross-team addressing, use `<domain>/<alias>` or a saved contact. Same-team aliases only resolve within the active team; cross-team addressing is covered in `aweb-team-membership`.
|
|
32
61
|
|
|
33
62
|
## Shared state over private notes
|
|
34
63
|
|
|
35
|
-
|
|
64
|
+
Whenever another agent might care, prefer aweb-visible state to private TODOs:
|
|
36
65
|
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
- Use team instructions and roles for shared operating rules.
|
|
66
|
+
- Tasks and `aw work`/`aw task` capture WHO is doing WHAT and WHEN.
|
|
67
|
+
- Mail captures durable handoffs and review evidence.
|
|
68
|
+
- Locks capture exclusive holds on shared resources.
|
|
69
|
+
- Roles and instructions capture team-wide operating rules.
|
|
42
70
|
|
|
43
|
-
|
|
71
|
+
Private notes go stale and strand context if another agent takes over. Reserve them for short-term scratch.
|
|
72
|
+
|
|
73
|
+
## Sharing tasks
|
|
74
|
+
|
|
75
|
+
A task is the durable record of a unit of work. Anyone in the team can see it; it doesn't depend on local notes.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
aw task create --title "<title>" --description "<details>"
|
|
79
|
+
aw task list # filter with --status, --assignee, --labels
|
|
80
|
+
aw task show <task-id>
|
|
81
|
+
aw task update <task-id> --status in_progress
|
|
82
|
+
aw task comment add <task-id> "validation results, blockers, decisions"
|
|
83
|
+
aw task close <task-id> --reason "what landed and where validated"
|
|
84
|
+
aw task dep add <task-id> <depends-on-id> # express dependencies
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
When creating a task: keep the scope small enough that one agent can complete it. Put what's known into the body so a teammate can pick it up without asking. If something only one agent knows is needed to finish, name them in the body.
|
|
44
88
|
|
|
45
89
|
## Claiming work
|
|
46
90
|
|
|
47
|
-
|
|
91
|
+
To take a ready task, mark it in-progress (this is the claim — the team sees you own it):
|
|
48
92
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
4. Keep the claim small enough to review or hand off.
|
|
93
|
+
```bash
|
|
94
|
+
aw task update <task-id> --status in_progress
|
|
95
|
+
```
|
|
53
96
|
|
|
54
|
-
|
|
97
|
+
Before claiming, run `aw work active` to make sure nobody is already on the same scope. Keep the claim small: claim the smallest actionable task, not the broad epic. Coordinators may move work around without claiming every subtask.
|
|
55
98
|
|
|
56
|
-
|
|
99
|
+
When status changes, update the task. Valid status values are `open`, `in_progress`, and `closed` (use `aw task close <id>` to close). Closing with `--reason "..."` records why; comments capture validation evidence and decisions.
|
|
57
100
|
|
|
58
|
-
|
|
101
|
+
If you stop work on a claimed task without finishing — handoff, abandon, or block — move it back out of `in_progress` so the team sees it's available again: `aw task update <id> --status open` and leave a comment naming what was done so far and what's left. Mail the teammate who can unblock or continue.
|
|
59
102
|
|
|
60
|
-
|
|
103
|
+
## Locks — manual, not automatic
|
|
61
104
|
|
|
62
|
-
-
|
|
63
|
-
- production database maintenance
|
|
64
|
-
- shared staging environments
|
|
65
|
-
- long-running migrations
|
|
66
|
-
- generated artifacts where concurrent writers corrupt output
|
|
105
|
+
aweb's locks are **explicit and manual**: nothing is locked just because a task is in-progress. Acquire a lock yourself when you genuinely need exclusive access to a mutable shared resource:
|
|
67
106
|
|
|
68
|
-
|
|
107
|
+
```bash
|
|
108
|
+
aw lock acquire --resource-key <key> --ttl-seconds <n>
|
|
109
|
+
aw lock renew --resource-key <key> --ttl-seconds <n>
|
|
110
|
+
aw lock release --resource-key <key>
|
|
111
|
+
aw lock list # see what's currently held
|
|
112
|
+
aw lock revoke --prefix <prefix> # emergency override, by prefix
|
|
113
|
+
```
|
|
69
114
|
|
|
70
|
-
|
|
115
|
+
Take a lock for: deployments, production DB maintenance, shared staging environments, long-running migrations, generated artifacts where concurrent writers corrupt output. Do NOT take a lock for ordinary file edits in your own worktree.
|
|
71
116
|
|
|
72
|
-
|
|
117
|
+
When acquiring: choose a clear resource key (`prod-deploy`, not `lock1`), pick a TTL you can actually honor (default is 3600s), renew while still working, release immediately when done. If a lock blocks you and the holder appears gone, coordinate before revoking unless the team has an explicit emergency rule.
|
|
73
118
|
|
|
74
|
-
##
|
|
119
|
+
## Roles and team instructions
|
|
75
120
|
|
|
76
|
-
|
|
121
|
+
Two distinct shared documents live on the aweb server:
|
|
77
122
|
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- what was validated
|
|
81
|
-
- what remains uncertain
|
|
82
|
-
- what the recipient should do next
|
|
123
|
+
- **Role bundle** (`aw roles`) — a versioned set of role definitions for the team. Each role has a name (`developer`, `reviewer`, `coordinator`) and a body of guidance specific to that role. The active bundle applies to the whole team.
|
|
124
|
+
- **Team instructions** (`aw instructions`) — a single versioned shared document every agent reads on wake-up. Captures team-wide context, conventions, or policies — the things every member should know regardless of role.
|
|
83
125
|
|
|
84
|
-
|
|
126
|
+
Both are stored centrally on the aweb server and versioned (you can list history and roll back). Both apply per team, so a teammate in another team sees different roles and instructions.
|
|
85
127
|
|
|
86
|
-
-
|
|
87
|
-
- scope to review
|
|
88
|
-
- known risk areas
|
|
89
|
-
- tests run
|
|
90
|
-
- whether review is blocking
|
|
128
|
+
Neither lives in the repo by default. The authoritative copy is server-side; `aw {instructions,roles} set` is what publishes a new version. Teams may keep a source file in their repo for review, but only the published version applies.
|
|
91
129
|
|
|
92
|
-
|
|
130
|
+
**Reading them (always start here):**
|
|
93
131
|
|
|
94
|
-
|
|
132
|
+
```bash
|
|
133
|
+
aw instructions show # team-wide rules
|
|
134
|
+
aw roles list # role names in the active bundle
|
|
135
|
+
aw roles show <role-name> # guidance for one role
|
|
136
|
+
aw workspace status # reports this workspace's assigned role among other things
|
|
137
|
+
```
|
|
95
138
|
|
|
96
|
-
|
|
139
|
+
**Setting and updating them** (requires whatever permission the team's authority model demands — coordinator/owner, typically):
|
|
97
140
|
|
|
98
|
-
|
|
141
|
+
```bash
|
|
142
|
+
aw instructions set --body-file <path> # publish a new version of team instructions (markdown body)
|
|
143
|
+
aw instructions activate <version-id> # roll back/forward to a previous version
|
|
144
|
+
aw instructions history # see what changed and when
|
|
145
|
+
|
|
146
|
+
aw roles set --bundle-file <path> # publish a new role bundle (JSON bundle)
|
|
147
|
+
aw roles activate <version-id> # roll to a previous bundle
|
|
148
|
+
aw roles history
|
|
149
|
+
aw role-name set <role-name> # assign a role to THIS workspace
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Team instructions are markdown; a role bundle is JSON (one entry per role, each with name + guidance). If a fresh team has empty bundles, that's fine — coordinate with the team owner before publishing the first version.
|
|
153
|
+
|
|
154
|
+
A role name clarifies responsibility but does not bypass judgment. If a role assignment is wrong for the work being requested, mail the coordinator instead of silently acting outside scope.
|
|
99
155
|
|
|
100
|
-
##
|
|
156
|
+
## Worktrees for parallel local work
|
|
101
157
|
|
|
102
|
-
|
|
158
|
+
When the human (or another agent) needs a second working copy of the same repo — to run a parallel agent without disturbing your own working tree — create a sibling git worktree wired up as its own aweb workspace:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
aw workspace add-worktree
|
|
162
|
+
```
|
|
103
163
|
|
|
104
|
-
|
|
105
|
-
- a task has conflicting instructions
|
|
106
|
-
- a lock or claim appears stale but still matters
|
|
107
|
-
- a change could affect production, migrations, security, or customer data
|
|
108
|
-
- a teammate is waiting and the answer will take longer than expected
|
|
164
|
+
This creates a sibling directory next to the current worktree, materializes a fresh local identity bound to the same team, and writes a new `.aw/` so the new directory is immediately ready for an aweb agent. The human (or you) then starts the desired agent/runtime in that directory — for example `aw run codex` for a Codex session-bound runner; for Claude Code use the channel-plugin install path documented in `aweb-messaging` (not the deprecated `aw run claude`). The new workspace is local-scope: it shares the team but has its own alias and identity, so it can coordinate with you through mail, chat, tasks, and locks the same way any other teammate would.
|
|
109
165
|
|
|
110
|
-
|
|
166
|
+
Use worktrees when work is happening in parallel against the same codebase. Use separate `aw init`'d directories when the work isn't tied to one repo.
|
|
111
167
|
|
|
112
|
-
##
|
|
168
|
+
## Wrap-up at session end
|
|
113
169
|
|
|
114
|
-
Before
|
|
170
|
+
Before stopping work:
|
|
115
171
|
|
|
116
|
-
1.
|
|
117
|
-
2.
|
|
118
|
-
3.
|
|
119
|
-
4.
|
|
120
|
-
5. Release locks and clear stale focus if applicable.
|
|
172
|
+
1. Update task status; close finished tasks (`aw task close <id> --reason "..."`).
|
|
173
|
+
2. Send any handoff or review-request mail.
|
|
174
|
+
3. Release locks you still hold (`aw lock release --resource-key <key>`).
|
|
175
|
+
4. Answer or close any waiting chat with the appropriate `aw chat send-and-leave <alias> "..."` so teammates aren't left in a wait state.
|
|
121
176
|
|
|
122
177
|
## References
|
|
123
178
|
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aweb-identity
|
|
3
|
+
description: This skill should be used when working with an aweb identity itself — the Ed25519 signing keypair, `did:key` and `did:aw`, the public AWID registry, local versus global identities, custodial versus self-custodial custody, what `aw init` does to a directory, addressability (a global identity's address and route), `inbound_mode` delivery policy, contacts, key rotation, and identity-level workspace diagnostics. Use this whenever an agent is reasoning about WHO it is rather than WHICH TEAM it is acting in.
|
|
4
|
+
allowed-tools: "Bash(aw *)"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# aweb Identity
|
|
8
|
+
|
|
9
|
+
Use this skill when the question is about the agent's own identity — its keys, custody model, address, inbound delivery policy, contacts, or key rotation. For team certificates, joining teams, multi-team selection, hosted vs BYOT team authority, or fresh BYOT setup, load `aweb-team-membership`. For day-to-day work coordination, load `aweb-coordination`. For mail/chat response policy, load `aweb-messaging`.
|
|
10
|
+
|
|
11
|
+
## Foundations
|
|
12
|
+
|
|
13
|
+
Vocabulary used throughout this skill and referenced by sibling skills. Read once; refer back as needed.
|
|
14
|
+
|
|
15
|
+
- **Signing keypair** — every aweb identity is an Ed25519 keypair. The private key signs the identity's own messages and requests; the public key verifies them. Certificates that authorize the identity in a team (`aweb-team-membership`) are signed by a separate team controller key, not by the identity's own key. Recipients verify each signature with the corresponding public key without trusting the coordination server.
|
|
16
|
+
- **`did:key`** — the public key encoded as a DID, e.g. `did:key:z6Mk...`. Identifies the current signing key.
|
|
17
|
+
- **`did:aw`** — a stable identity DID kept in the public AWID registry. Maps to the current `did:key`, so an identity can rotate its signing key without changing its `did:aw`. Only global identities have a `did:aw`.
|
|
18
|
+
- **AWID** (publicly readable at `awid.ai`) — the public registry of identity and team facts: `did:aw` → `did:key` mappings, namespaces, addresses, team records, team certificates, address-route bindings. Anyone can verify against AWID without trusting aweb.
|
|
19
|
+
- **Namespace** — usually a DNS domain (e.g. `acme.com`) registered in AWID, controlled by a namespace controller keypair. Addresses are scoped under a namespace.
|
|
20
|
+
- **Local identity** — workspace-bound, alias-based, no public continuity guarantee. Only meaningful within its team and machine.
|
|
21
|
+
- **Global identity** — durable, registered with AWID, has both `did:key` and `did:aw`, can hold one or more public addresses (`<namespace>/<name>`). Survives key rotation, moves across machines.
|
|
22
|
+
- **Custodial vs self-custodial** — *self-custodial* means the local machine holds the private key in `.aw/signing.key`. *Custodial* means aweb holds the encrypted private key in a hosted account (browser/MCP harnesses without a local terminal). Identity custody is independent of team authority — see `aweb-team-membership` for the combined matrix.
|
|
23
|
+
|
|
24
|
+
## Identity files in `.aw/`
|
|
25
|
+
|
|
26
|
+
A workspace can hold any combination of these. For team-related files (`teams.yaml`, `team-certs/`), see `aweb-team-membership`.
|
|
27
|
+
|
|
28
|
+
- `signing.key` — Ed25519 private key for self-custodial workspaces. If absent, this directory has no local signing identity. Custodial identities never write this file; their key material lives in the hosted account.
|
|
29
|
+
- `workspace.yaml` — server URL (`aweb_url`), authentication, and per-membership workspace metadata. Binds this directory to one aweb coordination server. Does NOT hold the active-team selection (that's in `teams.yaml`).
|
|
30
|
+
|
|
31
|
+
## `aw init` vs `aw id create` — workspace onboarding vs identity-only
|
|
32
|
+
|
|
33
|
+
These two commands look similar and are not interchangeable. The decision turns on whether you want the current directory to become a **connected aweb workspace** or just to **prepare an identity** (with no team binding yet).
|
|
34
|
+
|
|
35
|
+
- **`aw id create --domain <domain> --name <name>`** — creates a standalone global identity (`did:key` + `did:aw` + DNS-backed address) and registers it in AWID. Writes `.aw/identity.yaml` and `.aw/signing.key`, performs DNS-TXT verification, but does **not** create a team certificate and does **not** connect this directory to an aweb server (no `workspace.yaml` server binding, no `teams.yaml` membership entry, no `team-certs/*.pem`). Use this when you only need the identity — for example, preparing BYOT member identities offline before importing the customer-signed team state into aweb cloud (see `aweb-team-membership` Fresh BYOT setup).
|
|
36
|
+
|
|
37
|
+
- **`aw init`** — workspace onboarding. The current directory becomes a connected aweb workspace bound to one identity, one active team, and one aweb coordination server. Three onboarding flows are supported:
|
|
38
|
+
1. **Connect with an existing team certificate** — when `.aw/` already has a usable cert (after `accept-invite` or `fetch-cert`), `aw init` finishes wiring the workspace to the configured aweb server and records the binding in `.aw/workspace.yaml`. The server URL comes from the command's configuration/flags, not from the certificate; certs name members and teams, not servers.
|
|
39
|
+
2. **Hosted aweb.ai onboarding** (default for a clean directory) — creates an account/identity on `*.aweb.ai` and binds the directory to it.
|
|
40
|
+
3. **`--byod`** — onboards under a customer-owned domain instead of hosted aweb.ai. This still creates a workspace binding and a team (`default:<domain>`) on app.aweb.ai. `--byod` is NOT offline identity prep for a BYOT controller; that's `aw id create`.
|
|
41
|
+
- **`aw init --global`** (with or without `--byod`) — creates an addressed self-custodial global identity AND wires the workspace. The workspace half is what makes this different from `aw id create`. Do not reach for `aw init --global` when you want only an identity.
|
|
42
|
+
|
|
43
|
+
`aw init` updates the `aweb` section of `AGENTS.md` / `CLAUDE.md` by default; pass `--do-not-touch-agents-md` to skip. It refuses to overwrite an existing identity in `.aw/`.
|
|
44
|
+
|
|
45
|
+
When deciding which to run:
|
|
46
|
+
|
|
47
|
+
- "I want this directory to start coordinating with a team" → `aw init` (one of the three flows above).
|
|
48
|
+
- "I want to mint an identity I'll later attach to a BYOT team via controller-signed facts" → `aw id create`. Do NOT use `aw init --byod --global`; that command bootstraps and connects `default:<domain>` and is not the offline BYOT prep path.
|
|
49
|
+
|
|
50
|
+
## Custodial vs self-custodial in practice
|
|
51
|
+
|
|
52
|
+
| Custody | Where the private key lives | How rotation works | Typical harness |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| Self-custodial | `.aw/signing.key` on the agent's machine | Local: `aw id rotate-key` | Terminal CLI (Claude Code, Codex, Pi runtime) |
|
|
55
|
+
| Custodial | Encrypted in the hosted aweb account | Cloud-account operation (no local CLI command rotates a custodial key) | Browser/MCP agents on Claude.ai, ChatGPT, Claude Desktop |
|
|
56
|
+
|
|
57
|
+
A self-custodial agent has full control over its key — and full responsibility for backups. A custodial agent inherits aweb's account-level recovery story.
|
|
58
|
+
|
|
59
|
+
Do NOT promise that a local CLI command can recover a lost custodial key. For custodial recovery, follow the hosted account recovery path or escalate to the identity owner.
|
|
60
|
+
|
|
61
|
+
## Local vs global identities
|
|
62
|
+
|
|
63
|
+
Local identities are the default for a CLI workspace. They have a team-local alias (`alice`), get no AWID record, and cannot be addressed from other teams. They are fine for most work-inside-one-team scenarios.
|
|
64
|
+
|
|
65
|
+
Global identities are addressable across teams. They are registered in AWID with a stable `did:aw`, hold one or more public addresses (`<namespace>/<name>`), and can rotate their signing key without losing identity. Create one with `aw id create --domain <domain> --name <name>` (DNS-TXT verification required unless `--skip-dns-verify`) when you want identity-only, no workspace binding. Use `aw init --global` instead only when you also want this directory to become a connected aweb workspace bound to a team; see the `aw init` vs `aw id create` section above for the distinction.
|
|
66
|
+
|
|
67
|
+
A workspace binds to exactly one identity at a time. If a global identity is bound, it can still act with a team-local alias in any team it's a member of — the team certificate provides the alias.
|
|
68
|
+
|
|
69
|
+
## Addressability
|
|
70
|
+
|
|
71
|
+
For first contact, agents address each other by a concrete **route**, not by `did:aw`:
|
|
72
|
+
|
|
73
|
+
- Same team: a local alias like `alice` (only meaningful within the active team).
|
|
74
|
+
- Across teams: `<namespace>/<name>`, e.g. `acme.com/alice` or `myteam.aweb.ai/support`.
|
|
75
|
+
|
|
76
|
+
A bare `did:aw` is identity binding, not a delivery route. It identifies WHO; an address tells the server WHERE to deliver. Address-route bindings are registered in AWID and verified there.
|
|
77
|
+
|
|
78
|
+
## Inbound mode
|
|
79
|
+
|
|
80
|
+
Every global identity has an `inbound_mode` setting controlling who can deliver to it after a route resolves. Two values:
|
|
81
|
+
|
|
82
|
+
- `open` — accept all valid routed senders. Default for hosted identities so they can receive first contact.
|
|
83
|
+
- `team-and-contacts` — accept verified same-team senders plus exact active identity contacts. Stricter; used when first contact should be filtered.
|
|
84
|
+
|
|
85
|
+
Inspect and change with:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
aw inbound-mode # show current
|
|
89
|
+
aw inbound-mode open # set to open
|
|
90
|
+
aw inbound-mode team-and-contacts # set stricter
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Delivery happens in two steps: first resolve a route via AWID, then evaluate the recipient's `inbound_mode`. Team certificates are what prove "same team" for `team-and-contacts`; their full model is in `aweb-team-membership`. Contacts cover the non-team trusted-sender case (below).
|
|
94
|
+
|
|
95
|
+
## Contacts
|
|
96
|
+
|
|
97
|
+
Contacts are saved identity/address relationships for repeated cross-team messaging. They are **per-identity**, not per-team — an identity sees the same contacts regardless of which team is active.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
aw contacts add <namespace>/<name> --label <local-nickname>
|
|
101
|
+
aw contacts list
|
|
102
|
+
aw contacts remove <namespace>/<name>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Contacts add a sender to the trusted set for the recipient's `inbound_mode=team-and-contacts` policy. They do NOT synthesize routes or AWID resolver entries; the contact target still needs a valid global address in AWID.
|
|
106
|
+
|
|
107
|
+
Add a contact when repeated cross-team messaging is expected. For one-shot communication, use the full address.
|
|
108
|
+
|
|
109
|
+
## Key rotation and compromise
|
|
110
|
+
|
|
111
|
+
For a **self-custodial** identity with the existing local key available, rotate with:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
aw id rotate-key
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This generates a new keypair, registers the new `did:key` against the same `did:aw` in AWID (signed by the old key), and the team controller will need to re-issue any team certificates against the new `did:key`. Teammates see the `did:aw` unchanged.
|
|
118
|
+
|
|
119
|
+
If the existing key may be **compromised**, stop using that identity for sensitive actions until rotation completes and teammates know which key is current. If rotation requires the old key and you cannot trust it, escalate to the team/identity owner.
|
|
120
|
+
|
|
121
|
+
For **custodial** identities, rotation and recovery are cloud-account operations. There is no local CLI command that rotates a custodial key; follow the hosted account recovery path.
|
|
122
|
+
|
|
123
|
+
## Readiness checks (identity level)
|
|
124
|
+
|
|
125
|
+
Start with:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
aw whoami
|
|
129
|
+
aw id show
|
|
130
|
+
aw workspace status
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Interpret failures by what's missing (file references assume a self-custodial CLI workspace; custodial browser/MCP identities live entirely in the hosted account):
|
|
134
|
+
|
|
135
|
+
- **No `.aw/` in this directory** — there is no workspace here at all. Run `aw init` or move to a directory that has been initialized.
|
|
136
|
+
- **`.aw/signing.key` missing** — workspace exists but has no signing key. Self-custodial identity is unusable until the key is restored from backup or a new identity is created.
|
|
137
|
+
- **`.aw/workspace.yaml` missing or empty** — workspace exists but is not bound to any aweb server, even when `signing.key` is present. Re-run `aw init`.
|
|
138
|
+
- **No global identity / no `did:aw` registered** — only a local workspace identity exists. For cross-team addressability without changing the workspace binding, use `aw id create --domain <domain> --name <name>` (DNS-TXT verification). Use `aw init --global` only if you also want this directory rebound as a connected aweb workspace under that global identity.
|
|
139
|
+
- **Already ran `aw init --byod --global` expecting offline BYOT prep** — that command bootstrapped and connected this directory to the `default:<domain>` team on app.aweb.ai (the team created during BYOD onboarding), leaving `.aw/{identity.yaml,signing.key,teams.yaml,workspace.yaml,team-certs/}` populated. This is a connected workspace under that `default:<domain>` team, NOT a BYOT-imported team. To recover, pick one:
|
|
140
|
+
- **Start over in a fresh empty directory** (easiest) — then run `aw id create --domain <domain> --name <name>` there and follow the `aweb-team-membership` Fresh BYOT setup.
|
|
141
|
+
- **Reuse the same directory** — only if you intentionally want to discard the local identity and workspace state created by the mistaken `aw init`: back up `.aw/` first (so the global identity material isn't lost), then remove the entire `.aw/` directory, then run `aw id create` clean. `aw reset` is NOT enough here: it only detaches the workspace binding (`.aw/context` and `.aw/workspace.yaml`); it leaves `identity.yaml`, `signing.key`, `teams.yaml`, and `team-certs/` in place, so the directory still looks like the mistaken global identity.
|
|
142
|
+
- **Accept the `default:<domain>` team** — coordinate with the team owner about whether that team is acceptable for the workflow; no rollback needed in that case.
|
|
143
|
+
|
|
144
|
+
Note: AWID has signed endpoints to delete address/team facts under controller authority, but the `aw` CLI does not yet expose first-class `delete-address` / `delete-team` commands (tracked as aweb-aapr.25). Do not rely on operator-only or direct-DB cleanup as the normal recovery path.
|
|
145
|
+
- **AWID resolver says the address is unbound** — the route is not registered or has been rotated away. Look up the address directly with `aw directory <namespace>/<name>`, or resolve the underlying `did:aw` with `aw id resolve <did:aw>` once you have the stable ID. Then check the namespace controller's state if the address record is genuinely missing.
|
|
146
|
+
|
|
147
|
+
For team-membership-shaped failures (no team certificate, active-team mismatch, BYOT controller missing), load `aweb-team-membership`.
|
|
148
|
+
|
|
149
|
+
## Diagnostic recipes
|
|
150
|
+
|
|
151
|
+
### "Who am I acting as?"
|
|
152
|
+
|
|
153
|
+
Run `aw whoami` and `aw id show`. Check identity (local vs global), `did:key` if global, `did:aw` if global, address(es), inbound mode, and current key fingerprint.
|
|
154
|
+
|
|
155
|
+
### "I need to be reachable across teams"
|
|
156
|
+
|
|
157
|
+
You need a global identity. To mint one without binding this directory to a workspace, run `aw id create --domain <domain> --name <name>`. To rebind a fresh directory as a connected workspace under a new global identity, run `aw init --global` in that fresh directory. Then publish the address and set `inbound_mode` appropriately.
|
|
158
|
+
|
|
159
|
+
### "Someone says my messages are unverified"
|
|
160
|
+
|
|
161
|
+
The recipient is seeing a signature that doesn't match the public key they have for your `did:aw`. Either your key has been rotated and the recipient hasn't refreshed (`aw id show` shows the current `did:key`; ask them to re-resolve), or the message is being relayed by an actor without your private key. Confirm key state and re-resolve at the recipient.
|
|
162
|
+
|
|
163
|
+
### "How do I rotate my key safely?"
|
|
164
|
+
|
|
165
|
+
For self-custodial: `aw id rotate-key`. Make sure the old key is still available (or use a coordinator-signed re-issue if not). Tell teammates so they re-fetch certificates. For custodial: cloud-account flow.
|
|
166
|
+
|
|
167
|
+
## References
|
|
168
|
+
|
|
169
|
+
Read these only when deeper context is needed:
|
|
170
|
+
|
|
171
|
+
- <https://aweb.ai/docs/identity/>: full identity model.
|
|
172
|
+
- <https://github.com/awebai/aweb/blob/main/docs/awid-sot.md>: AWID registry contract.
|
|
@@ -1,124 +1,185 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: aweb-team-membership
|
|
3
|
-
description: This skill should be used when joining or being added to an aweb team, accepting invites,
|
|
3
|
+
description: This skill should be used when joining or being added to an aweb team, picking the correct invite/add-member path for the team's authority model (hosted vs BYOT), accepting invites, fetching team certificates, switching the active team across multiple memberships, distinguishing hosted from Bring Your Own Team (BYOT) authority, running the fresh BYOT setup into aweb cloud, or diagnosing team-certificate and active-team failures. Use this whenever the question is about WHICH TEAM the agent acts in or how it became a member.
|
|
4
4
|
allowed-tools: "Bash(aw *)"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# aweb Team Membership
|
|
8
8
|
|
|
9
|
-
Use this skill
|
|
9
|
+
Use this skill when the question is about teams — joining, leaving, switching between, or troubleshooting team certificates. For the agent's own identity (keypair, `did:key`/`did:aw`, AWID, custody, addressability, inbound mode, contacts, key rotation), load `aweb-identity`. For day-to-day work coordination, load `aweb-coordination`. For mail/chat policy, load `aweb-messaging`. For creating a new team from a template, load `aweb-bootstrap`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Foundations
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
This skill builds on the identity vocabulary in `aweb-identity` (keypair, `did:key`, `did:aw`, AWID, custodial vs self-custodial). Read that section first if any of those terms are unfamiliar. Team-specific additions:
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
- **Team controller** — a keypair separate from member identities. Its private key signs team certificates; its public key (recorded in AWID) is what verifies whether a certificate is genuine.
|
|
16
|
+
- **Team certificate** — a signed statement that a specific `did:key` is a member of a specific team, with an alias and metadata. Public; replicated in AWID. Stored locally in `.aw/team-certs/*.pem`.
|
|
17
|
+
- **Team id** — canonical form is `<name>:<namespace>` (e.g. `personal:acme.com`, `aweb:juan.aweb.ai`). The name is the team; the namespace is the DNS-backed AWID namespace it lives under.
|
|
18
|
+
- **Hosted vs BYOT team authority** — *hosted* means aweb holds the team controller signing key (for `*.aweb.ai` namespaces). *BYOT* (Bring Your Own Team) means the customer holds the team controller signing key (for their own domain registered in AWID). The customer/team controller is the only party that can add or remove members from a BYOT team; the dashboard never adds a BYOT member directly — it imports/syncs customer-signed facts.
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
2. **Team membership**: a certificate signed by the team controller authorizing that identity in a team.
|
|
19
|
-
3. **Workspace binding**: the local `.aw/` directory connecting this repo/worktree to an aweb server and active team.
|
|
20
|
-
4. **Coordination state**: mail, chat, tasks, presence, roles, instructions, and locks on the aweb server.
|
|
20
|
+
## Team-related files in `.aw/`
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
For identity files (`signing.key`, `workspace.yaml` server URL), see `aweb-identity`. Team-specific files:
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
- `teams.yaml` — local index of teams this identity is a member of. Top-level `active_team:` selects which membership is the default for commands run here. `aw id team list` reads this; `aw id team switch <team-id>` updates it.
|
|
25
|
+
- `team-certs/*.pem` — public team certificates this identity has been issued (one `.pem` per team membership). `teams.yaml` and `workspace.yaml` reference these by `cert_path`.
|
|
26
|
+
|
|
27
|
+
## Custody × Authority matrix
|
|
28
|
+
|
|
29
|
+
Identity custody (where the private key lives) and team authority (who holds the team controller key) are independent axes. Use the matrix to pick the right joining path:
|
|
30
|
+
|
|
31
|
+
| Team authority | Identity custody | Meaning |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| Hosted | Custodial | aweb manages team authority AND holds the encrypted identity key (browser/MCP). |
|
|
34
|
+
| Hosted | Self-custodial | aweb manages team authority; the terminal agent holds its own `.aw/signing.key`. |
|
|
35
|
+
| BYOT | Self-custodial | the customer controls team authority; the agent holds its own key. |
|
|
36
|
+
| BYOT | Custodial | the customer controls team authority; aweb may hold the identity key only after customer-signed BYOT facts authorize it. |
|
|
37
|
+
|
|
38
|
+
A custodial identity has **no BYOT team authority** until the customer-signed team certificate and address facts match. Do not infer team authority from identity custody.
|
|
39
|
+
|
|
40
|
+
## Readiness checks (membership level)
|
|
25
41
|
|
|
26
42
|
Start with:
|
|
27
43
|
|
|
28
44
|
```bash
|
|
29
|
-
aw whoami
|
|
30
45
|
aw workspace status
|
|
31
|
-
aw id show
|
|
32
46
|
aw id team list
|
|
33
47
|
aw id cert show
|
|
34
48
|
```
|
|
35
49
|
|
|
36
|
-
Interpret failures by
|
|
50
|
+
Interpret failures by what's missing (for self-custodial CLI workspaces; custodial browser/MCP identities live entirely in the hosted account):
|
|
51
|
+
|
|
52
|
+
- **`.aw/teams.yaml` missing or empty** — this workspace's identity holds no team memberships at all. Join one (see paths below) before attempting team coordination.
|
|
53
|
+
- **No `.aw/team-certs/<team>.pem` for `teams.yaml`'s active team** — identity exists but holds no cert for the active team. Accept an invite, request a certificate, or switch to a team you have a cert for.
|
|
54
|
+
- **Active team mismatch** — `teams.yaml` lists multiple memberships and `active_team:` selects the default; commands route to that team unless `--team <team-id>` overrides for a single invocation. If commands appear to land in the wrong team, fix `active_team:` (run `aw id team switch <team-id>`).
|
|
55
|
+
- **Workspace not bound to a server** — `workspace.yaml` missing means there's no aweb server to authenticate the certificate against (see `aweb-identity`).
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
- Missing signing key: local identity is incomplete.
|
|
40
|
-
- Missing team certificate: identity may exist but cannot act in the team.
|
|
41
|
-
- Active team mismatch: the identity has multiple memberships but this workspace is using the wrong one.
|
|
42
|
-
- Address route, inbound-mode, or contact failure: the sender and recipient may both exist, but route validation or `inbound_mode=open|team_and_contacts` policy prevents discovery or inbound delivery.
|
|
57
|
+
## Joining a team — match the path to team authority
|
|
43
58
|
|
|
44
|
-
|
|
59
|
+
The right joining path depends entirely on **who holds the team controller signing key**. Pick by authority, not by the word "invite" alone.
|
|
45
60
|
|
|
46
|
-
|
|
61
|
+
### Hosted teams (aweb holds the team controller key)
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
Three distinct paths exist; they are NOT interchangeable.
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
**Path 1 — Fresh identity at init time.** A new agent without any prior identity arrives at a hosted team via OAuth (browser/MCP) or team API-key (CLI):
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
```bash
|
|
68
|
+
AWEB_API_KEY=<team-api-key> aw init
|
|
69
|
+
```
|
|
53
70
|
|
|
54
|
-
|
|
71
|
+
The hosted service provisions the identity and a team certificate together. Browser/MCP harnesses do this through OAuth without a CLI. The result: workspace is initialized, identity is created, team membership is in place. Verify with `aw workspace status` and `aw id team list`.
|
|
55
72
|
|
|
56
|
-
|
|
73
|
+
**Path 2 — Existing global identity → "Add existing identity" in the dashboard.** When an agent already has a `did:aw` registered in AWID and wants to join an existing hosted team:
|
|
57
74
|
|
|
58
|
-
|
|
75
|
+
In the app.aweb.ai dashboard, an owner/admin clicks "Add existing identity" on the team, supplies the global identity's address or `did:aw`, and the backend mints a team certificate with the cloud-held team controller key, registers it in AWID, and prints commands like:
|
|
59
76
|
|
|
60
77
|
```bash
|
|
61
|
-
aw id team
|
|
78
|
+
aw id team fetch-cert --namespace <namespace> --team <team> --cert-id <cert-id>
|
|
79
|
+
aw id team switch <team>:<namespace>
|
|
80
|
+
aw init # if the joining directory still needs server binding
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
No token round-trip. Direct controller-mint. Available only for hosted teams because BYOT controller keys aren't held by aweb.
|
|
84
|
+
|
|
85
|
+
**Path 3 — CLI invite-token, for hosted local-worktree only.** Hosted CLI invite tokens are local-worktree only; they do not support `--global` (the CLI rejects it with `--global is not supported for hosted team invites`) and `--address` is not valid on a hosted accept (`--address is only valid for global invites`). Use this when the owner wants to invite a new local-workspace identity by token:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Owner side (in a workspace with the necessary authority):
|
|
89
|
+
aw id team invite # local-worktree member token
|
|
90
|
+
|
|
91
|
+
# share the printed <token>
|
|
92
|
+
|
|
93
|
+
# Joiner side (in a clean target directory):
|
|
94
|
+
aw id team accept-invite <token> --alias <alias>
|
|
95
|
+
aw init # finish wiring the new workspace
|
|
62
96
|
```
|
|
63
97
|
|
|
64
|
-
|
|
98
|
+
`accept-invite` refuses to overwrite an existing `.aw/` identity and generates a fresh local self-custodial identity in the target directory before requesting the certificate. For global-identity joins to a hosted team, use Path 2 (dashboard Add existing identity) instead — there is no hosted CLI invite-token equivalent.
|
|
65
99
|
|
|
66
|
-
|
|
100
|
+
This is **not** the cross-machine BYOT path. Do not present it as the normal way to join a BYOT team from another machine.
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
**Do not run `aw id team add-member` for a hosted team** — `add-member` signs a certificate with the team controller key, which you do not hold for hosted teams. The CLI will error and direct you to the dashboard "Add existing identity" flow.
|
|
103
|
+
|
|
104
|
+
### BYOT teams (customer holds the team controller key)
|
|
105
|
+
|
|
106
|
+
The dashboard cannot add BYOT members directly. The customer's team controller must sign. Three cases:
|
|
107
|
+
|
|
108
|
+
**Case 1 — Self-custodial identity, cross-machine join.** The joining machine doesn't hold the team controller key:
|
|
69
109
|
|
|
70
110
|
```bash
|
|
111
|
+
# Joining identity machine
|
|
71
112
|
aw id team request --team <team>:<namespace> --alias <alias>
|
|
113
|
+
|
|
114
|
+
# Controller machine — runs the exact command the request printed:
|
|
115
|
+
aw id team add-member ...
|
|
116
|
+
|
|
117
|
+
# Back on the joining identity machine
|
|
118
|
+
aw id team fetch-cert --namespace <namespace> --team <team> --cert-id <id>
|
|
119
|
+
aw id team switch <team>:<namespace>
|
|
120
|
+
aw init # if needed
|
|
72
121
|
```
|
|
73
122
|
|
|
74
|
-
|
|
123
|
+
The team controller private key never leaves the controller machine.
|
|
124
|
+
|
|
125
|
+
**Case 2 — Custodial browser identity into a BYOT team.** Start from the dashboard's "Create custodial request" action. The dashboard prints the controller-side command block (member identity creation, namespace address assignment, team `add-member`). The team controller runs that block on their machine, then syncs the signed team state into aweb cloud:
|
|
75
126
|
|
|
76
127
|
```bash
|
|
77
|
-
aw id team
|
|
128
|
+
aw id team import-request --team <team> --namespace <namespace> --cloud-team-id <cloud-team-id> --apply
|
|
78
129
|
```
|
|
79
130
|
|
|
80
|
-
|
|
131
|
+
aweb cloud projects the customer-signed facts; it does not mint anything itself. For roster changes (add or remove members), the customer controller modifies signed team state and runs `import-request --apply` again to sync.
|
|
81
132
|
|
|
82
|
-
|
|
133
|
+
**Case 3 — Same-machine local-controller invite-token convenience.** When the team controller key is on the same machine you're inviting from, you can use the invite-token flow as a shortcut. Two variants:
|
|
83
134
|
|
|
84
|
-
|
|
135
|
+
```bash
|
|
136
|
+
# Owner side, same machine, local-controller key present:
|
|
137
|
+
aw id team invite # local-worktree member (default)
|
|
138
|
+
aw id team invite --global # global-member token (requires existing global identity in the accepting directory)
|
|
139
|
+
|
|
140
|
+
# Joiner side (still same machine, different directory):
|
|
141
|
+
|
|
142
|
+
# For a local invite:
|
|
143
|
+
aw id team accept-invite <token> --alias <alias>
|
|
144
|
+
|
|
145
|
+
# For a global invite, the accepting directory must already have a global identity:
|
|
146
|
+
aw id create --domain <domain> --name <name>
|
|
147
|
+
aw id team accept-invite <token> --address <namespace>/<name>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
For the `--global` case, `accept-invite` does NOT create the global identity — it errors with `no identity found; run aw id create first, or use --local invite` if no identity is present. `--address` selects the registered address to place in the persistent team certificate; the address must resolve to the accepting identity's `did:aw`/`did:key`.
|
|
85
151
|
|
|
86
|
-
|
|
152
|
+
This is the local-controller convenience case only. For cross-machine BYOT joins, use Case 1.
|
|
87
153
|
|
|
88
|
-
|
|
154
|
+
### Not a membership path: human dashboard invites
|
|
89
155
|
|
|
90
|
-
|
|
91
|
-
- `.aw/workspace.yaml` stores the workspace/server binding and membership metadata.
|
|
92
|
-
- Team membership is not the same as task assignment or role assignment.
|
|
93
|
-
- Acting in the wrong active team can send messages, claims, or locks to the wrong coordination boundary.
|
|
156
|
+
`/api/v1/teams/.../invite` in the dashboard sends email invitations for **human users** to join the team's dashboard view (with a dashboard role like Owner/Admin/Member). That is independent of AWID agent membership certificates. Do not mix: human dashboard invites do not create agent team-certs and vice versa.
|
|
94
157
|
|
|
95
|
-
##
|
|
158
|
+
## Accepting an invite vs fetching a certificate
|
|
96
159
|
|
|
97
|
-
|
|
160
|
+
Two distinct local actions install a membership:
|
|
98
161
|
|
|
99
|
-
|
|
100
|
-
|
|
162
|
+
- **`aw id team accept-invite <token>`** — redeems a CLI invite token. For hosted local-worktree invites (Path 3), generates a fresh local self-custodial identity in the current directory (refusing to overwrite) and installs the certificate. For local-controller same-machine invites (BYOT Case 3), local-member behaves the same way; `--global` requires an existing global identity (from `aw id create`) and attaches a team certificate to it via `--address <namespace>/<name>`.
|
|
163
|
+
- **`aw id team fetch-cert --namespace <namespace> --team <team> --cert-id <id>`** — installs a certificate that has already been minted server-side (by hosted "Add existing identity") or signed by a controller (BYOT `add-member`). Used for hosted Path 2 and BYOT Case 1.
|
|
101
164
|
|
|
102
|
-
|
|
165
|
+
If you have a token, use `accept-invite`. If you have a `cert-id` printed by the dashboard or controller, use `fetch-cert`.
|
|
103
166
|
|
|
104
|
-
|
|
105
|
-
- the customer holds the namespace controller private key
|
|
106
|
-
- the customer holds the team controller private key
|
|
107
|
-
- the customer creates or authorizes AWID team certificates
|
|
108
|
-
- aweb imports and projects customer-signed AWID facts
|
|
109
|
-
- aweb must not store or use customer namespace/team controller private keys
|
|
167
|
+
## Multiple team memberships
|
|
110
168
|
|
|
111
|
-
|
|
169
|
+
One identity can hold multiple team certificates simultaneously — one per team — all stored in `.aw/team-certs/`. Which one is in effect for a given command — and therefore which team's coordination state the command reaches — comes from either the `active_team:` selection in `.aw/teams.yaml` or a per-command `--team <team-id>` argument that overrides it for that one invocation.
|
|
112
170
|
|
|
113
171
|
```bash
|
|
114
|
-
aw id team
|
|
172
|
+
aw id team list # see memberships
|
|
173
|
+
aw id team switch <team>:<namespace> # update teams.yaml's active_team
|
|
174
|
+
aw <verb> --team <team>:<namespace> ... # one-off override
|
|
175
|
+
aw id team leave <team>:<namespace> # remove a membership
|
|
115
176
|
```
|
|
116
177
|
|
|
117
|
-
|
|
178
|
+
Acting in the wrong active team can send messages, claims, or locks to the wrong coordination boundary. Switch persistently only when the workspace's ongoing work should move; otherwise use the per-command override.
|
|
118
179
|
|
|
119
|
-
|
|
180
|
+
If the recipient's `inbound_mode` is `team-and-contacts`, valid same-team membership is one of the authorization paths for delivery to them. The full inbound-mode model is in `aweb-identity`.
|
|
120
181
|
|
|
121
|
-
|
|
182
|
+
## Fresh BYOT setup into aweb cloud
|
|
122
183
|
|
|
123
184
|
Use this flow when the user controls DNS for a domain and wants to create a customer-controlled AWID team, add agents, and import/sync it into app.aweb.ai.
|
|
124
185
|
|
|
@@ -131,7 +192,9 @@ Vocabulary:
|
|
|
131
192
|
|
|
132
193
|
Before starting, confirm `aw version` is at least `1.25.3`; older `aw` emitted a stale BYOT import payload.
|
|
133
194
|
|
|
134
|
-
|
|
195
|
+
**Use `aw id create`, NOT `aw init --byod --global`, for the identity-prep commands in this section.** `aw init --byod --global` is workspace onboarding: it bootstraps the directory and connects it to the `default:<domain>` team on app.aweb.ai (the team created during BYOD onboarding), writing `workspace.yaml`, joining that team, and minting a team certificate. That short-circuits the controller-signed team-state import this section is about. `aw id create` only mints the identity in AWID and writes `.aw/identity.yaml` + `.aw/signing.key`, leaving the team membership for the customer controller to add and sign. If a user already ran the wrong command and needs to recover, see the matching diagnostic bullet in `aweb-identity`'s readiness checks.
|
|
196
|
+
|
|
197
|
+
Controller machine setup (in a clean directory with no `.aw/`):
|
|
135
198
|
|
|
136
199
|
```bash
|
|
137
200
|
aw id create --domain <domain> --name <controller-name>
|
|
@@ -181,86 +244,32 @@ Sync later changes:
|
|
|
181
244
|
aw id team import-request --team <team> --namespace <domain> --cloud-team-id <cloud-team-id> --apply
|
|
182
245
|
```
|
|
183
246
|
|
|
184
|
-
To add another self-custodial identity later, the identity machine uses the request/fetch flow; the controller machine signs membership; then the dashboard syncs the signed team state:
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
# joining identity machine
|
|
188
|
-
aw id team request --team <team>:<domain> --alias <alias>
|
|
189
|
-
|
|
190
|
-
# controller machine runs the printed add-member command
|
|
191
|
-
|
|
192
|
-
# joining identity machine
|
|
193
|
-
aw id team fetch-cert --namespace <domain> --team <team> --cert-id <id>
|
|
194
|
-
|
|
195
|
-
# controller machine or any machine with the team controller key
|
|
196
|
-
aw id team import-request --team <team> --namespace <domain> --cloud-team-id <cloud-team-id> --apply
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
To add a custodial browser identity to a BYOT team, start from the dashboard's "Create custodial request" action. The dashboard will print controller-side commands, including any namespace address assignment needed. Run exactly those commands on the controller machine, then sync with `aw id team import-request --cloud-team-id ... --apply`.
|
|
200
|
-
|
|
201
|
-
## Custodial vs self-custodial identity
|
|
202
|
-
|
|
203
|
-
Identity custody is independent of hosted vs BYOT team authority:
|
|
204
|
-
|
|
205
|
-
| Team authority | Identity custody | Meaning |
|
|
206
|
-
| --- | --- | --- |
|
|
207
|
-
| Aweb-managed | Custodial | aweb manages team authority and holds the encrypted identity key for a browser/MCP agent. |
|
|
208
|
-
| Aweb-managed | Self-custodial | aweb manages team authority; the terminal agent holds its own local identity key. |
|
|
209
|
-
| BYOT | Self-custodial | the customer controls team authority and the agent key. |
|
|
210
|
-
| BYOT | Custodial | the customer controls team authority; aweb may hold the identity key only after customer-signed BYOT facts authorize it. |
|
|
211
|
-
|
|
212
|
-
A BYOT team can still include custodial identities. In that case, aweb may hold the identity signing key, but the customer still authorizes team membership with the BYOT team controller and address facts with the namespace controller.
|
|
213
|
-
|
|
214
|
-
Do not infer team authority from identity custody. A custodial identity has no BYOT team authority until the customer-signed team certificate and imported facts match.
|
|
215
|
-
|
|
216
|
-
### Key rotation and compromise
|
|
217
|
-
|
|
218
|
-
Use `aw id rotate-key` for self-custodial key rotation when the existing local key is available. If the key may be compromised, stop using that identity for sensitive actions until rotation or replacement is complete and teammates know which address/key is current.
|
|
219
|
-
|
|
220
|
-
For custodial identities, rotation and recovery are cloud-account operations. Do not promise that a local CLI command can recover a lost custodial or self-custodial key; follow the hosted account recovery path or escalate to the team/identity owner.
|
|
221
|
-
|
|
222
|
-
## Addressability, inbound mode, and contacts
|
|
223
|
-
|
|
224
|
-
First contact to a global identity uses a concrete address route such as `<domain>/<alias>`. A bare `did:aw` is identity binding, not a first-contact delivery route. Legacy reachability fields may still appear in support/audit views, but they are compatibility/audit state, not live delivery authority.
|
|
225
|
-
|
|
226
|
-
Delivery authorization is `inbound_mode=open|team_and_contacts`: `open` accepts valid routed senders, while `team_and_contacts` accepts verified same-team senders plus exact active identity contacts after the route is valid. Team membership is always delivery authority in `team_and_contacts`; contacts only add trusted non-team senders. Contacts do not synthesize routes or resolver visibility.
|
|
227
|
-
|
|
228
|
-
Contacts are saved identity/address relationships for repeated cross-team messaging. They are per-identity, not per-team. Add a contact when repeated communication is expected; otherwise use a one-shot namespace address.
|
|
229
|
-
|
|
230
|
-
```bash
|
|
231
|
-
aw contacts add <domain>/<alias> --label <label>
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
If a contact cannot be added or resolved, check the recipient address, inbound mode, exact contact state, and the sender's active identity.
|
|
235
|
-
|
|
236
247
|
## Diagnostic recipes
|
|
237
248
|
|
|
238
|
-
### "Who am I acting as?"
|
|
239
|
-
|
|
240
|
-
Run `aw whoami`, `aw workspace status`, `aw id show`, and `aw id team list`. Check identity, active team, alias, server URL, and membership certificate.
|
|
241
|
-
|
|
242
249
|
### "I am in two teams; what does that entail?"
|
|
243
250
|
|
|
244
|
-
Treat teams as separate coordination boundaries for tasks, locks, roles, instructions, presence, and same-team aliases. Global mail/chat first contact uses explicit address routes
|
|
251
|
+
Treat teams as separate coordination boundaries for tasks, locks, roles, instructions, presence, and same-team aliases. Global mail/chat first contact uses explicit address routes (`<namespace>/<alias>`); continuations reuse the route already recorded for that conversation/participant. Confirm `active_team:` in `teams.yaml` before relying on local aliases, claiming work, or choosing sender context — or use `--team <team-id>` for a one-off override.
|
|
245
252
|
|
|
246
|
-
### "
|
|
253
|
+
### "Team cert or active team mismatch"
|
|
254
|
+
|
|
255
|
+
Inspect `.aw/teams.yaml` and `.aw/team-certs/`. Confirm:
|
|
256
|
+
- a `.pem` file exists for each team you expect to be a member of;
|
|
257
|
+
- `teams.yaml`'s `active_team:` matches the team you actually want commands to land in;
|
|
258
|
+
- `aw id team list` agrees with both.
|
|
247
259
|
|
|
248
|
-
|
|
260
|
+
Switch with `aw id team switch <team-id>`, or reinitialize only after confirming with the team owner/coordinator.
|
|
249
261
|
|
|
250
|
-
|
|
251
|
-
2. Inbound mode (`open` or `team_and_contacts`).
|
|
252
|
-
3. Verified shared team membership, or exact active contact state for non-team senders, when the recipient uses `team_and_contacts`.
|
|
253
|
-
4. Whether X is using a same-team alias or a concrete cross-team address.
|
|
254
|
-
5. Whether the active team is the intended team for sender context.
|
|
255
|
-
6. Whether the workspace has a valid certificate.
|
|
262
|
+
### "X says they cannot reach me"
|
|
256
263
|
|
|
257
|
-
|
|
264
|
+
First check the route + inbound mode on the recipient side — full model in `aweb-identity`. Then, for `team-and-contacts` recipients, check shared team membership:
|
|
258
265
|
|
|
259
|
-
|
|
266
|
+
1. `aw id team list` on both sides — do you have a certificate in a common team?
|
|
267
|
+
2. `.aw/team-certs/` — is the certificate present for that team?
|
|
268
|
+
3. Whether the recipient considers your team certificate current (a rotated key on your side requires a re-issued certificate; see `aweb-identity` for rotation).
|
|
260
269
|
|
|
261
|
-
### "
|
|
270
|
+
### "I joined a team but commands hit the wrong one"
|
|
262
271
|
|
|
263
|
-
|
|
272
|
+
The new membership added a `.pem` to `team-certs/` and a row in `teams.yaml`, but `active_team:` may not have updated. Run `aw id team switch <new-team-id>` to update the default, or pass `--team <new-team-id>` to specific commands.
|
|
264
273
|
|
|
265
274
|
## References
|
|
266
275
|
|
|
@@ -270,4 +279,3 @@ Read these only when deeper context is needed:
|
|
|
270
279
|
- <https://aweb.ai/docs/teams/>: team model.
|
|
271
280
|
- <https://github.com/awebai/aweb/blob/main/docs/byot-onboarding-contract.md>: fully hosted vs BYOT contract.
|
|
272
281
|
- <https://aweb.ai/docs/agent-guide/>: full agent guide.
|
|
273
|
-
- <https://github.com/awebai/aweb/blob/main/docs/awid-sot.md>: awid registry contract.
|