@awebai/pi 0.1.14 → 0.1.15

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/README.md CHANGED
@@ -40,7 +40,7 @@ Then restart pi (recommended; ensures packages/extensions are reloaded) or run:
40
40
 
41
41
  When aweb channel events arrive, the extension wakes the running pi session with:
42
42
 
43
- - the mail/chat/control/work event contents
43
+ - the mail/chat/control/work event contents for legacy/server-readable events, or metadata-only notifications for encrypted v2 E2E content until local decryption succeeds
44
44
  - sender and conversation metadata
45
45
  - sender/authorship verification status
46
46
  - a prominent warning if verification fails or is unknown
@@ -53,6 +53,8 @@ Delivery behavior:
53
53
 
54
54
  On the first ready session for a workspace/team, the extension also injects a one-time welcome message that orients the agent to the aweb work loop and points at the bundled skills. The welcome is sentinel-gated under `~/.config/aw/pi-welcome.json` so reloads do not repeat it.
55
55
 
56
+ For encrypted v2 E2E messages, plaintext may be shown or injected only after local decryption in the Pi/workspace process. Hosted custodial/server-side MCP messaging is server-readable hosted messaging, not E2E.
57
+
56
58
  The agent responds with normal shell commands, for example:
57
59
 
58
60
  ```bash
@@ -78,11 +80,13 @@ This package exposes the canonical aweb Agent Skills via `pi.skills`, so one ins
78
80
  - channel awakenings
79
81
  - instructions for using `aw` effectively
80
82
 
81
- Bundled v1 skills:
83
+ Bundled skills:
82
84
 
83
- - `aweb-coordination` — session/work-loop policy for teams of agents.
85
+ - `aweb-bootstrap` — creating or joining a team from a template; team source, work directory, and worktree-agent decisions.
86
+ - `aweb-identity` — the agent's own identity: keypair, `did:key`/`did:aw`, the AWID registry, custodial vs self-custodial custody, addressability, inbound mode, contacts, key rotation.
87
+ - `aweb-team-membership` — joining teams, multi-team membership, hosted vs BYOT team authority, team certificates, fresh BYOT setup, custody × authority.
88
+ - `aweb-coordination` — session/work-loop policy for teams of agents: tasks, claims, locks, roles, instructions, worktrees.
84
89
  - `aweb-messaging` — mail/chat/channel-awakening response policy.
85
- - `aweb-team-membership` — joining teams, multi-team membership, hosted vs BYOT, custody, addressability, inbound mode, and contacts.
86
90
 
87
91
  The canonical skill bodies live at the repository root under `skills/`; this package copies them into the npm package for Pi rather than maintaining a separate Pi-only fork. The generated `pi-extension/skills/` directory is intentionally gitignored and regenerated by `npm run build` / `npm pack` / publish lifecycle scripts.
88
92
 
@@ -93,5 +97,6 @@ The extension uses `@awebai/channel-core`, shared with `@awebai/claude-channel`,
93
97
  - aweb signed API calls
94
98
  - SSE event subscription and reconnect
95
99
  - mail/chat fetch and read/ack behavior
100
+ - encrypted-message event handling that keeps server notifications metadata-only and leaves plaintext display to local decryption
96
101
  - sender signature verification and trust normalization
97
102
  - formatting awakenings with trust warnings
package/dist/index.js CHANGED
@@ -6338,7 +6338,7 @@ To enable aweb awakenings in pi:
6338
6338
 
6339
6339
  2. Then restart pi or run /reload.
6340
6340
 
6341
- Once initialized, incoming aweb mail/chat/control events will wake this pi session with message contents and sender verification status. Use the aw CLI from pi's bash tool to respond.`;
6341
+ Once initialized, incoming aweb mail/chat/control events will wake this pi session with message content for legacy/server-readable events, or metadata-only notifications for encrypted E2E content until local decryption succeeds, plus sender verification status. Use the aw CLI from pi's bash tool to respond.`;
6342
6342
  }
6343
6343
  function welcomeKey(cwd, teamID, alias) {
6344
6344
  return `${WELCOME_VERSION}:${teamID}:${alias}:${cwd}`;
@@ -6363,7 +6363,7 @@ async function markWelcomeSeen(key) {
6363
6363
  function welcomeMessage(alias, teamID) {
6364
6364
  return `aweb for Pi is ready.
6365
6365
 
6366
- You are connected as ${alias} in team ${teamID}. This package gives Pi two aweb capabilities: real-time channel awakenings for mail/chat/control events, and the canonical aweb skills for the aw CLI.
6366
+ You are connected as ${alias} in team ${teamID}. This package gives Pi two aweb capabilities: real-time channel awakenings for mail/chat/control events, and the canonical aweb skills for the aw CLI. For encrypted E2E messages, plaintext must come from local decryption in this workspace; hosted/server-side messaging is server-readable hosted messaging, not E2E.
6367
6367
 
6368
6368
  First moves:
6369
6369
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awebai/pi",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
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",
@@ -76,10 +76,36 @@ Canonical templates:
76
76
  - awebai/aweb-team-company-surfaces (6 agents)
77
77
  Use when you want a cross-functional team: direction/engineering/operations/support/outreach/analytics.
78
78
 
79
- Fork vs use-as-is:
79
+ Fork/edit vs use-as-is:
80
80
 
81
81
  - Use as-is to learn the flow or to run a standard team.
82
- - Fork when you want to customize roles, responsibilities, or instructions.
82
+ - Clone or fork when you want to customize roles, responsibilities, or instructions before provisioning.
83
+ - It is safe to edit the template checkout before applying it; `aw team bootstrap` reads `team.yaml`, `roles/`, `docs/`, and `agents/` from the local template directory at run time.
84
+
85
+ ## Customizing a template before applying it
86
+
87
+ When the human wants different agents, role playbooks, names, or instructions, do not try to patch the generated workspaces after bootstrap. Clone/edit the template first, then bootstrap the edited local directory.
88
+
89
+ Typical safe flow:
90
+
91
+ ```bash
92
+ git clone https://github.com/awebai/aweb-team-dev-review.git my-team-template
93
+ cd my-team-template
94
+ # edit team.yaml, roles/*.md, docs/team.md, agents/<responsibility>/AGENTS.md
95
+ aw team bootstrap . --dry-run --work-directory /path/to/work
96
+ aw team bootstrap . --work-directory /path/to/work
97
+ ```
98
+
99
+ What to edit:
100
+
101
+ - `team.yaml` roles: add/remove role names and point each to a role file.
102
+ - `team.yaml` agents: add/remove responsibility workspaces and set each `role_name`, `default_name`, and `default_alias`.
103
+ - `team.yaml` worktrees: add/remove local git-worktree agents for code work.
104
+ - `roles/*.md`: change operational playbooks installed with `aw roles`.
105
+ - `docs/team.md`: change shared team instructions installed after the anchor connects.
106
+ - `agents/<responsibility>/AGENTS.md`: change per-workspace startup context.
107
+
108
+ Default agent names are accepted automatically. Only use `--ask-for-agent-names` when a human specifically wants an interactive rename prompt during bootstrap.
83
109
 
84
110
  ## Before running bootstrap (safety checks)
85
111
 
@@ -159,7 +185,7 @@ Supported sources:
159
185
 
160
186
  Decision recipe:
161
187
 
162
- - Human says “make me a new team” and has no existing aw context: use hosted (`--username` or interactive prompt). If using `--yes`, include `--username`; otherwise omit `--yes` so hosted onboarding can prompt.
188
+ - Human says “make me a new team” and has no existing aw context: use hosted (`--username` or interactive prompt).
163
189
  - Human has a dashboard/API key: use `AWEB_API_KEY=... aw team bootstrap ...`; do not ask for `AWEB_URL` unless they are using a non-default stack.
164
190
  - Human pasted an invite: use `--invite-token`.
165
191
  - Human is already inside the team workspace that should own the new agents: use current workspace forwarding (no explicit source).
@@ -30,13 +30,13 @@ Checklist:
30
30
  - awebai/aweb-team-dev-review for a minimal 2-agent setup.
31
31
  - awebai/aweb-team-company-surfaces for a 6-agent cross-functional setup.
32
32
 
33
- Example (using an existing local work directory, with an explicit hosted username so --yes does not need prompts):
33
+ Example (using an existing local work directory):
34
34
 
35
- aw team bootstrap https://github.com/awebai/aweb-team-dev-review.git --yes --username alice --work-directory /path/to/work
35
+ aw team bootstrap https://github.com/awebai/aweb-team-dev-review.git --username alice --work-directory /path/to/work
36
36
 
37
37
  Example (clone the work repo into the template checkout):
38
38
 
39
- aw team bootstrap https://github.com/awebai/aweb-team-dev-review.git --yes --username alice --work-repo-url https://github.com/ORG/REPO.git
39
+ aw team bootstrap https://github.com/awebai/aweb-team-dev-review.git --username alice --work-repo-url https://github.com/ORG/REPO.git
40
40
 
41
41
  Notes:
42
42
 
@@ -47,6 +47,25 @@ Notes:
47
47
 
48
48
  where derived-name is the git-style repo directory name (basename with .git stripped).
49
49
 
50
+ ## Scenario: customize the template before applying it
51
+
52
+ Goal: change roles, agent responsibilities, names, aliases, or instructions before any team state is created.
53
+
54
+ Checklist:
55
+
56
+ - Clone or fork the template first.
57
+ - Edit `team.yaml`, `roles/*.md`, `docs/team.md`, and `agents/<responsibility>/AGENTS.md` as needed.
58
+ - Run `aw team bootstrap . --dry-run ...` from the template checkout to validate.
59
+ - Bootstrap the local directory only after the plan looks right.
60
+
61
+ Example:
62
+
63
+ git clone https://github.com/awebai/aweb-team-dev-review.git my-team-template
64
+ cd my-team-template
65
+ # edit team.yaml / roles / docs / agents
66
+ aw team bootstrap . --dry-run --work-directory /path/to/work
67
+ aw team bootstrap . --username alice --work-directory /path/to/work
68
+
50
69
  ## Scenario: BYOT (bring your own team)
51
70
 
52
71
  Goal: bootstrap a team under a namespace/domain you control.
@@ -60,7 +79,6 @@ Checklist:
60
79
  Example shape (values are placeholders):
61
80
 
62
81
  aw team bootstrap https://github.com/awebai/aweb-team-dev-review.git \
63
- --yes \
64
82
  --namespace example.com \
65
83
  --team dev \
66
84
  --work-directory /path/to/work
@@ -1,6 +1,6 @@
1
1
  ---
2
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.
3
+ description: This skill should be used when working with an aweb identity itself — the Ed25519 signing keypair, E2E encryption keys, `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
4
  allowed-tools: "Bash(aw *)"
5
5
  ---
6
6
 
@@ -13,6 +13,7 @@ Use this skill when the question is about the agent's own identity — its keys,
13
13
  Vocabulary used throughout this skill and referenced by sibling skills. Read once; refer back as needed.
14
14
 
15
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
+ - **Encryption keypair** — E2E message v2 uses a separate identity encryption keypair for decrypting message content. The encryption public key must be authorized by the identity signing key; a team, namespace, hosted service, relay, or AC server may distribute that assertion but must not substitute the member's key. Signing keys authenticate; encryption keys decrypt.
16
17
  - **`did:key`** — the public key encoded as a DID, e.g. `did:key:z6Mk...`. Identifies the current signing key.
17
18
  - **`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
19
  - **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.
@@ -26,6 +27,7 @@ Vocabulary used throughout this skill and referenced by sibling skills. Read onc
26
27
  A workspace can hold any combination of these. For team-related files (`teams.yaml`, `team-certs/`), see `aweb-team-membership`.
27
28
 
28
29
  - `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.
30
+ - `encryption.yaml` and `encryption-keys/` — local E2E message-decryption keyring. `encryption.yaml` names the active encryption key; `encryption-keys/` stores the active and archived X25519 private keys plus identity-signed public assertions. Back these up with the workspace. Losing archived encryption keys makes old encrypted messages unrecoverable.
29
31
  - `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
32
 
31
33
  ## `aw init` vs `aw id create` — workspace onboarding vs identity-only
@@ -55,10 +57,30 @@ When deciding which to run:
55
57
  | Custody | Where the private key lives | How rotation works | Typical harness |
56
58
  | --- | --- | --- | --- |
57
59
  | Self-custodial | `.aw/signing.key` on the agent's machine | Local: `aw id rotate-key` | Terminal CLI (Claude Code, Codex, Pi runtime) |
58
- | 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 |
60
+ | Custodial | Identity signing key material is held in the hosted aweb account (not a local E2E message-decryption key) | Cloud-account operation (no local CLI command rotates a custodial key) | Browser/MCP agents on Claude.ai, ChatGPT, Claude Desktop |
59
61
 
60
62
  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.
61
63
 
64
+ ## E2E encryption key boundary
65
+
66
+ The normative E2E contract is `docs/e2e-messaging-contract.md`. Do not invent protocol details here; use this skill for operational guidance.
67
+
68
+ For local E2E messaging, the self-custodial client needs both identity signing material and local encryption private keys. Back up the active encryption private key and archived encryption private keys with the same seriousness as `.aw/signing.key`: losing archived encryption keys makes historical encrypted messages unrecoverable. AC/aweb cannot recover or decrypt old encrypted messages for support.
69
+
70
+ An identity must publish an identity-signed encryption-key assertion before it can receive E2E messages. Missing, stale, unsigned, or mismatched encryption-key discovery fails closed; do not retry as plaintext unless the human explicitly chooses the separately named legacy plaintext mode from the final CLI. Service signatures may assert route support, but not recipient encryption-key authority. Local identities omit absent `stable_id`/address fields instead of sending empty strings. In non-interactive runs, stop, report the exact `aw doctor` / command error, and ask the human or coordinator to run the approved key setup, backup, or rotation flow.
71
+
72
+ Use the CLI keyring commands for self-custodial E2E readiness:
73
+
74
+ ```bash
75
+ aw id encryption-key setup # create/publish the active key if needed
76
+ aw id encryption-key rotate # publish a new active key; keep archived keys
77
+ aw id encryption-key show # inspect local keyring state
78
+ ```
79
+
80
+ `setup` stores the private key locally before publishing the public assertion. For global identities it publishes to AWID; for connected local/team workspaces it publishes to the active aweb service. `rotate` must not delete old private keys. After either command, remind the human to back up `.aw/encryption-keys/`.
81
+
82
+ Hosted custodial MCP, dashboard-side send/read, and other server-side tools are **server-readable hosted messaging**, not E2E, because plaintext or decryption capability enters AC/aweb. Do not tell users that hosted custodial/server-side messaging is end-to-end encrypted unless a future design keeps plaintext and decryption fully outside AC.
83
+
62
84
  AWID controller keys are separate from worktree identity keys. Namespace and team controller keys live under `~/.awid/`; they are authority keys, not app config. Keep that directory safe and backed up. Worktree identity keys (`.aw/signing.key`) remain with the workspace they act from.
63
85
 
64
86
  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.
@@ -123,7 +145,7 @@ This generates a new keypair, registers the new `did:key` against the same `did:
123
145
 
124
146
  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.
125
147
 
126
- 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.
148
+ 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. Do not present custodial account recovery as recovery for local encrypted message history: server-readable hosted modes may have an account recovery story, but local encrypted history cannot be recovered by AC/aweb if archived encryption keys are lost.
127
149
 
128
150
  ## Readiness checks (identity level)
129
151
 
@@ -139,6 +161,7 @@ Interpret failures by what's missing (file references assume a self-custodial CL
139
161
 
140
162
  - **No `.aw/` in this directory** — there is no workspace here at all. Run `aw init` or move to a directory that has been initialized.
141
163
  - **`.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.
164
+ - **E2E encryption-key check fails** — distinguish the cases the CLI reports: missing local encryption private key, missing published encryption-key assertion, stale/mismatched assertion, or missing archived key for an older message. Do not advise plaintext fallback. Capture the exact error, run `aw doctor` when available, and ask the human to restore keys from backup or run `aw id encryption-key setup` / `aw id encryption-key rotate` as appropriate.
142
165
  - **`.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`.
143
166
  - **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.
144
167
  - **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:
@@ -10,6 +10,10 @@ This skill is the playbook for aweb channel awakenings. When you receive an inje
10
10
 
11
11
  It also covers explicit user requests to send mail or chat through aweb.
12
12
 
13
+ E2E messaging boundary: for encrypted v2 messages, AC/aweb servers route ciphertext and local clients decrypt before showing or injecting plaintext. Hosted custodial MCP, dashboard-side send/read, and server-side tools are **server-readable hosted messaging**, not E2E. Do not describe hosted custodial/server-side messaging as end-to-end encrypted.
14
+
15
+ Legacy plaintext boundary: existing plaintext mail/chat remains legacy/server-readable while retained and must not be described as retroactively E2E. If an intended E2E send fails because keys, capability, route support, or version support is missing/stale/mismatched, stop and report the exact failure. Do not resend as plaintext unless the human explicitly chooses the approved legacy plaintext command/flag.
16
+
13
17
  If the event says to use the aw CLI and the response is not obvious, continue with this skill. For broader work coordination, load `aweb-coordination`. For recipient addressability, inbound-mode policy, team membership, or multi-team identity questions, load `aweb-team-membership`.
14
18
 
15
19
  ## Read the event first
@@ -73,9 +77,19 @@ aw chat extend-wait <from> "working on it, 2 minutes"
73
77
 
74
78
  Before replying to a confusing chat, inspect pending/open/history state. Do not use chat for broad FYI updates. Send mail instead.
75
79
 
80
+ Encrypted chat is explicit. Use `--e2ee` only when the human or policy asks for E2E chat and every participant has identity-authorized encryption capability:
81
+
82
+ ```bash
83
+ aw chat send-and-wait <alias-or-address> "..." --start-conversation --e2ee
84
+ aw chat send-and-leave <alias-or-address> "..." --e2ee
85
+ aw chat extend-wait <from> "working on it" --e2ee
86
+ ```
87
+
88
+ Read paths such as `aw chat pending`, `aw chat history`, and channel listen/decrypt paths show plaintext only after local decryption. If `--e2ee` fails because a key, capability, route, or version is missing or stale, stop and report the exact error; do not resend as plaintext unless the human explicitly chooses the approved legacy plaintext path.
89
+
76
90
  ## Harness surfaces
77
91
 
78
- Terminal agents, Pi, and Claude Code can use the `aw` CLI directly. Custodial MCP/OAuth agents may have equivalent MCP tools for mail/chat. For Claude Code, do not use deprecated `aw run claude`; install the `aweb-channel` plugin for push events. Use the harness-native surface, but keep the same decision policy:
92
+ Terminal agents, Pi, and Claude Code can use the `aw` CLI directly. Custodial MCP/OAuth agents may have equivalent MCP tools for mail/chat, but those hosted/server-side tool calls are server-readable hosted messaging unless plaintext and decryption stay fully outside AC/aweb. For Claude Code, do not use deprecated `aw run claude`; install the `aweb-channel` plugin for push events. Use the harness-native surface, but keep the same decision policy:
79
93
 
80
94
  - async update → mail
81
95
  - synchronous blocker → chat
@@ -95,6 +109,8 @@ Harness support differs:
95
109
 
96
110
  The channel is inbound only. Use `aw mail` or `aw chat` to respond.
97
111
 
112
+ For E2E messages, channel/Pi/`aw run` may show plaintext only after local decryption in the user's workspace or client process. Server notifications and SSE payloads should be metadata-only for encrypted content. Recipient E2E capability and encryption keys must be identity-authorized; a service signature can assert route support only. If an event or tool error says an encryption key/capability is missing, stale, or mismatched, fail closed and report the error. Do not silently resend as plaintext.
113
+
98
114
  ## Control and work awakenings
99
115
 
100
116
  For control signals:
@@ -12,8 +12,8 @@ Use this skill when the question is about teams — joining, leaving, switching
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
- - **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`.
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. Team controllers authorize membership; they do not decrypt member conversations and must not substitute a member's E2E encryption key.
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`. A certificate proves team membership; it is not a message-decryption key.
17
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
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.
19
19
 
@@ -30,13 +30,15 @@ Identity custody (where the private key lives) and team authority (who holds the
30
30
 
31
31
  | Team authority | Identity custody | Meaning |
32
32
  | --- | --- | --- |
33
- | Hosted | Custodial | aweb manages team authority AND holds the encrypted identity key (browser/MCP). |
33
+ | Hosted | Custodial | aweb manages team authority AND holds hosted identity signing key material (browser/MCP). Messaging in this mode is server-readable hosted messaging, not E2E. |
34
34
  | Hosted | Self-custodial | aweb manages team authority; the terminal agent holds its own `.aw/signing.key`. |
35
35
  | BYOT | Self-custodial | the customer controls team authority; the agent holds its own key. |
36
36
  | BYOT | Custodial | the customer controls team authority; aweb may hold the identity key only after customer-signed BYOT facts authorize it. |
37
37
 
38
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
39
 
40
+ For E2E messaging, custody and team membership are still not enough by themselves: the recipient's encryption public key must be identity-authorized as described in `docs/e2e-messaging-contract.md`. Team/namespace authority may distribute that assertion, but it must not replace the member's key. If an encryption-key check fails, do not suggest a team-controller workaround or plaintext fallback; stop and route the user to the approved identity/key setup or recovery flow.
41
+
40
42
  ## Readiness checks (membership level)
41
43
 
42
44
  Start with: