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
security(service-datasource): require manage_platform_settings on the datasource-admin routes (#9887)
* security(service-datasource): require manage_platform_settings on the datasource-admin routes
The datasource-admin HTTP family took any authenticated caller once #9391 landed
its anonymous floor. Datasource create/patch/remove/introspect are
platform-configuration actions, so all eleven routes now also require the
capability the adjacent Setup-admin families gate on.
The capability is measured, not minted: service-settings' platform-infrastructure
namespaces (mail, storage, sms, auth, ai, knowledge) and objectql's lifecycle
namespace all declare manage_platform_settings for reads AND writes, while the
cohort that splits setup.access/setup.write is the tenant-cosmetic one. This
service's own Setup nav entry already declared requiredPermissions:
['manage_platform_settings'] on the console door in front of these routes, so
the change makes declared equal enforced.
Refusal is the standard-catalog 403 PERMISSION_DENIED through the shared
sendError, not the grandfathered FORBIDDEN synonym whose ADR-0112 waiver covers
three other packages and does not endorse the spelling for new code.
The both-sides-on-one-boot pin grows a third posture (entitled succeeds,
authenticated-but-unentitled is refused, anonymous stays refused), and the two
suites for which an entitled caller is the premise share its fixture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnJHU45vPJj5UQrxe946Bx
* test(rest): entitle the listRemoteTables twin fixture and pin the new capability divergence
The datasource-admin capability gate flips a public admission semantic, and the
twin-equivalence suite one package over was the consumer pin asserting the old
one: its fixture caller was authenticated but unentitled, so five request-shape
cases compared a 200 against the new 403 and read an admission difference as a
request-shape divergence.
The fixture now resolves grants through the platform's own RBAC chain — one fake
engine wired into BOTH spellings, the admin registrar's `objectql` lookup and the
resolveAuthzContext call behind the federation registrar's resolveExecutionContext,
so the twins still read one identity and now one grant aggregation.
The #9686 "WHO may ask" block keeps both refusal cases unchanged (anonymous and
unrecognised credential still refuse identically) and gains a case pinning what is
now true: an authenticated but unentitled caller is refused 403 PERMISSION_DENIED
at the admin spelling and served at the federation spelling. That asymmetry is
filed as #9901, not accepted; the case is labelled a record of a known gap and is
expected to fail when the gap closes.
No packages/rest runtime code is touched — gating the federation family is a
separate decision and a different lane.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnJHU45vPJj5UQrxe946Bx
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments