You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 96822ba
Browse filesBrowse the repository at this point in the historyBrowse files
feat(people): add people clients add/remove/invite/enable/disable (#689)
* Pin basecamp-sdk to the project-client-users branch
The client-admission operations (UpdateProjectClientAccess,
EnableProjectClients, DisableProjectClients) live on basecamp-sdk's
feat/project-client-users branch (basecamp/basecamp-sdk#847) ahead of a
release, so go.mod pins its head as a pseudo-version, the way the
bubble-up pin did. Re-pin to the tagged go/vX.Y.Z release once it is
cut, and re-sync the vendored MCP model and the Nix vendorHash from it.
The vendored MCP model is synced from that head: three People operations
join the catalog (served count 256 -> 259) and the seat-limit 429 on
UpdateProjectClientAccess is declared non-retryable (retry_on [503]).
* Add people clients: list, add, remove, invite, enable, disable
The client-side counterpart of people add/remove, over the endpoints
bc3#13098 shipped: PUT /projects/:id/people/client_users.json and
POST/DELETE /projects/:id/client_enablement.json.
A separate group rather than a --client flag: bc3 keeps the two kinds of
access apart on the wire (the team endpoint drops a client's id, the
client endpoint rejects a team member's), so the CLI mirrors the split.
The ids the server silently drops come back as a diagnostic notice.
invite takes a bare address or "Name <email>" (net/mail), or "-" for one
invitee per line on stdin; --company applies to every invitee, --title
to exactly one. Refusals map to verdicts: a 403 reads the project back
to name "clients not enabled" against a permission problem; the
all-or-nothing 422 exits validation naming each rejected row from the
SDK's field errors; the seat-limit 429 exits limit_exceeded, not a
retryable rate limit. disable's 403 reads the roster back so the hint
is the exact remove command.
people list now carries each person's client flag.
* Keep a seat-limit 429 from gating later commands; answer disable's 403 honestly
The resilience hooks persisted a 60-second block for every headerless
429, so the client seat-limit verdict would have refused unrelated
commands for a minute. OnOperationStart now names the operation in the
context and OnRequestEnd consults the SDK's declared retry set: an
operation that does not retry on 429 (UpdateProjectClientAccess) is one
the server answers 429 as a verdict, and it sets no block. A 429 that
names a Retry-After is honored as before.
disable's 403 names the remaining clients only when the roster shows
some; otherwise it is a plain denial, since the same 403 answers a
caller without permission. The seat-limit message no longer states a
count: existing addresses take no seat and repeats count once, and only
the server knows which rows those are.
* Re-pin basecamp-sdk to dcd9fbd6; reject stray positionals on the project-only verbs
The SDK branch head decodes the row-error selectors independently and
reports client access as project_access; the pin, provenance, vendored
MCP model, and Nix vendorHash follow it.
list, enable, and disable take no positional, so a stray one is refused
instead of discarded: with a default project configured, "disable 123"
would otherwise have acted on the configured project. The remove hint
disable offers separates ids with spaces so it pastes as a command.
* Name every malformed invitee at once, and say which errors are local
A token that is not an address is refused before any request as a usage
error; the help and skill text had promised the server's validation
exit for it. The local check now names every malformed token in one
error instead of stopping at the first, and the docs distinguish the
local refusal (usage, 2) from the server's all-or-nothing rejection
(validation, 9) and seat shortfall (limit_exceeded, 10).
people list's client flag is pinned by a test.
* Pin basecamp-sdk to v0.17.0
Copy file name to clipboardExpand all lines: API-COVERAGE.md
+7-4Lines changed: 7 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,12 +6,15 @@ Coverage of Basecamp 3 API endpoints. Source: [bc3-api/sections](https://github.
6
6
7
7
| Status | Sections | Endpoints |
8
8
|--------|----------|-----------|
9
-
| ✅ Implemented | 50 |189|
9
+
| ✅ Implemented | 50 |192|
10
10
| ⚠️ Blocked | 0 | 0 |
11
11
| ⏭️ Out of scope | 4 | 12 |
12
-
|**Total tracked**|**54**|**201**|
12
+
|**Total tracked**|**54**|**204**|
13
13
14
-
**189 of 189 tracked in-scope endpoints.** SDK v0.16.0 adds the three to-do
14
+
**192 of 192 tracked in-scope endpoints.** The client-admission endpoints
15
+
basecamp/bc3#13098 added — `PUT /projects/:id/people/client_users.json` and
16
+
`POST`/`DELETE /projects/:id/client_enablement.json` — land as `people clients`.
17
+
SDK v0.16.0 adds the three to-do
15
18
list template-library operations, available through `templates library`,
16
19
`templates copy`, and `templates copy-status`. The previous last gap — `GET
17
20
/uploads/:id/versions.json` — closed with the v0.14.0 SDK bump. The command
@@ -211,7 +214,7 @@ cannot faithfully cover at least one endpoint for a reason outside the CLI. A
211
214
| drafts | 1 |`drafts`| ✅ | BC5 | - | list unpublished drafts across projects (server caps at 250). Bounded like the account-wide listings; publishing happens through the command for the draft's type |
212
215
| my_notes | 2 |`notes`| ✅ | BC5 | - | show, set. A singleton per person, so no id and no listing. Pre-first-write the record does not exist yet and renders as empty rather than 404. `set` writes Markdown as HTML; attachments are out of scope |
213
216
|**People**|
214
-
| people |12|`people`, `me`| ✅ | BC4 | - | list, show, update (edit your own profile via `PUT /my/profile.json`), out-of-office show/set/clear (`GetOutOfOffice`/`EnableOutOfOffice`/`DisableOutOfOffice`), pingable, add, remove (BC5: `tagline` alias of `bio` on person output) |
217
+
| people |15|`people`, `me`| ✅ | BC4 | - | list, show, update (edit your own profile via `PUT /my/profile.json`), out-of-office show/set/clear (`GetOutOfOffice`/`EnableOutOfOffice`/`DisableOutOfOffice`), pingable, add, remove (BC5: `tagline` alias of `bio` on person output). `people clients` covers the client side: `add`/`remove`/`invite` through `PUT /projects/:id/people/client_users.json` (basecamp/bc3#13098), `enable`/`disable` through `POST`/`DELETE /projects/:id/client_enablement.json`; `list` is the project roster filtered to `client: true`|
215
218
|**Search & Recordings**|
216
219
| my_assignments | 6 |`assignments`| ✅ | BC4 | - | list (priorities/non-priorities), completed, due (with scope filter), prioritize, deprioritize, reorder. `list` surfaces `priority_recording_id`, which is the only way to address a prioritized card-table step — it appears in no URL |
0 commit comments