ποΈ PUT-1735 + PUT-1737 + PUT-1738 + PUT-1739: the puter.teams SDK module, suite and docs - #3741
Conversation
b5535ef to
6f375d8
Compare
|
Terminology: "master account" is now "owner account" throughout the workspace surface β docs, SDK JSDoc, GUI strings and backend comments. 24 files, no behavior change.
|
6f375d8 to
5d0e430
Compare
Terminology: "workspace" is now "team", everywhereThe feature said Applied to every commit rather than added on top, so each PR shows its own code already named correctly and no intermediate commit references a name a later one changes. All 13 commits still typecheck individually. The contract-bearing renamesThese were free to change now and expensive after release, which is why they went in this pass:
Plus Scoped, and checked"workspace" means other things in this repo. These were deliberately left alone, and verified untouched:
Audited three ways: every changed line mentions team or workspace (no collateral edits), no stutters or mangled words ( One thing not renamedThe git branch names still say |
5d0e430 to
6bd216e
Compare
6bd216e to
edb2aaf
Compare
edb2aaf to
794a0ce
Compare
794a0ce to
b5f905a
Compare
Local validation β SDK, suite and docsEngine mysql 8, a real local instance, current tip. Nothing stubbed but the SDK origin in the browser tests. The CI failure this PR had, and why it was mineEvery That is a collision between this PR and the cap in #3725, and it only appears when the two are stacked. Fixed in // The shipped default is 1, and the suite creates a team per case
// against one shared account, so every case after the first would
// fail on `team_limit_reached` rather than on what it tests.
max_teams_per_user: 100,β I had not run After the fix, run locally: The API surface, exercised end to endA 40-check transcript against the running server covers every route this SDK wraps. Extract: Two things the run taught me about the real flowsA provisioned seat has no
Neither is a defect, but neither is obvious from the docs, and both cost me a real debugging loop. VerificationTypecheck clean Β· |
Team administration reaches the backend through the `/teams` routes
rather than a driver interface, because the gates it needs are route-level:
a user actor, a verified account, and a dual-window rate limit.
The module follows `apps/` and `perms/` in layout -- one file per method,
a thin `index.js`, a JSDoc-only `types.js`, and the `METHODS` rebinding so a
destructured method keeps its `this`. It does not follow `perms/lib/req.js`:
those endpoints resolve `{ error: true }` for backward compatibility, and
nothing here has callers to keep compatible, so this throws `PuterJSError`
with the backend's own code.
Every method takes a team `uid`. A handle is a mutable label that
deleting the team releases, so a stored handle can later resolve to a
different team.
The list methods offer the three forms `puter.apps.list()` does -- an array
by default, the page envelope under `cursor`/`includeTotal`, an async
iterator under `stream`. They refuse `offset`: these routes are keyset-only
and would otherwise return page one however far you asked to skip.
The surface covers the routes that exist today. Usage totals and member-email
correction have no backend route yet and are deliberately absent rather than
shipped as methods that 404. `deleteMember()` is here because the route it
needs lands in the commit below this one.
b5f905a to
c9b234c
Compare
Closes PUT-1735, PUT-1737, PUT-1738 and PUT-1739. Stacked on #3740.
Four tickets, one surface: the module, the suite that exercises it, the pages that document it, and the limits those pages publish. Splitting them would mean shipping a module with no docs, then docs describing a module already merged.
Why routes and not a driver
Workspace administration reaches the backend through
/teamsrather than a driver interface, because the gates it needs are route-level: a user actor, a verified account, and a dual-window rate limit. A driver has none of those.Layout
Follows
apps/andperms/β one file per method, a thinindex.js, a JSDoc-onlytypes.js, and theMETHODSrebinding so a destructured method keeps itsthis.It deliberately does not follow
perms/lib/req.js. Those endpoints resolve{ error: true }for backward compatibility; nothing here has callers to keep compatible, so this throwsPuterJSErrorcarrying the backend's own code.Two decisions worth a reviewer's eye
Every method takes a
uid, never a handle. A handle is a mutable label that deleting the workspace releases, so a stored handle can later resolve to a different workspace. Accepting one would make that a silent wrong-target bug rather than a 404.The list methods refuse
offset. They offer the three formsputer.apps.list()does β array by default, page envelope undercursor/includeTotal, async iterator understream. These routes are keyset-only, so an acceptedoffsetwould return page one however far you asked to skip. Refusing beats lying.Scope
The surface covers the routes that exist today. Usage totals and member-email correction have no backend route yet and are absent rather than shipped as methods that 404.
deleteMember()is here β the route it needs lands in #3740, directly below this. Worth flagging: this PR is unmergeable ahead of that one, by design.Docs
Teams.mdplus 14 method pages, each carrying the beta banner in the same positionEvents/puts it β on every page, not only the index, since a reader arriving from search lands on a method page.Limits published in
rate-limits-and-quotas.md(PUT-1739), including that both buckets are per account rather than per workspace, so administering several workspaces spends one budget.Verification
Typecheck clean.
check:puterjs:typesβ declarations generate and type-check cleanly. Backend suite 7887 passed | 26 skipped. SDK unit tests 23 passed, and every commit in the stack typechecks on its own rather than just the tips.teams.suite.ts(PUT-1737) is registered insuites/index.tsand gated on the teams capability, so it skips where a deployment has teams off instead of failing.β
npm run check-translationscould not be run: the script points attools/check-translations.js, which does not exist onmaineither. Pre-existing, unrelated to this PR, and worth its own ticket.