Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); docs(comments): correct four docblock sites describing the retired platform-admin elevation gate by claude[bot] · Pull Request #13907 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions packages/plugins/plugin-auth/src/last-admin-guard.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -634,8 +634,21 @@ export const GRANT_STANDING_KEYS = [
* to say so: `resolveAuthzContext` derived `platform_admin` from the name
* alone and read no flag. It now drops a DEACTIVATED set before any
* derivation, so `active: false` on `admin_full_access` un-makes every
* platform admin at once — the same end state as renaming or deleting the
* row, reached by a payload that touches neither. Enforcing the flag without
* GRANT-anchored platform admin at once — the same end state as renaming or
* deleting the row, reached by a payload that touches neither. ⚠️ Not
* "every platform admin": since the #11663 re-anchor (L2) standing has a
* SECOND anchor this write cannot reach — a config-anchored administrator
* (a declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user`
* row) is derived at `resolve-authz-context.ts` §6b-config without
* consulting the set row or its `active` flag at all, and carries the
* shipped `ADMIN_FULL_ACCESS_CAPABILITIES` envelope rather than the stored
* set's. That is deliberately NOT a reason to drop `active` from this
* list: the write can still empty the GRANT anchor, which on every
* deployment that has declared no administrator emails is the whole
* population. Listing it is an over-approximation in the SAFE direction —
* it can cost an enumeration on a write that turns out to change no count,
* never the reverse — and taking it out would be a behaviour change, not a
* comment fix. Enforcing the flag without
* listing it here would have left exactly one unguarded route to an
* installation-wide lockout: the action is offered on every row with no
* visibility or condition guard, the seeders deliberately never reconcile
Expand All@@ -645,13 +658,16 @@ export const GRANT_STANDING_KEYS = [
* Everything else a permission-set write touches (`label`, `description`, the
* four permission JSON blobs, provenance) is still invisible to "who is an
* administrator" — `resolveAuthzContext` derives `platform_admin` from the NAME
* of an ACTIVE set, never from the capabilities it carries — so those writes
* still cost this guard no reads at all. Adding `active` does not walk that
* back: the projection is FACETS ONLY and deliberately never re-flips a
* record's on/off switch (`permission-set-projection.ts`, #4669), so every
* projection pass, every `os meta resync` and every ordinary Setup edit still
* misses this list entirely. What now pays for an enumeration is the write that
* actually toggles the switch — which is the write this list exists to judge.
* of an ACTIVE set or, since the #11663 re-anchor (L2), from the
* deployment-config anchor, and from the capabilities of neither (the config
* arm's envelope is the shipped `ADMIN_FULL_ACCESS_CAPABILITIES` declaration,
* not the stored row) — so those writes still cost this guard no reads at all.
* Adding `active` does not walk that back: the projection is FACETS ONLY and
* deliberately never re-flips a record's on/off switch
* (`permission-set-projection.ts`, #4669), so every projection pass, every
* `os meta resync` and every ordinary Setup edit still misses this list
* entirely. What now pays for an enumeration is the write that actually
* toggles the switch — which is the write this list exists to judge.
*
* `id` is deliberately NOT here even though the enumeration reads it. On this
* engine `data.id` on an update ADDRESSES the row (it is what
Expand All@@ -661,9 +677,12 @@ export const GRANT_STANDING_KEYS = [
*
* `sys_position` gets no analogous list because it has no route into this
* enumeration to guard: platform-admin standing is read from UNSCOPED
* `sys_user_permission_set` grants only (a position-bound `admin_full_access`
* never conferred it, in the resolver or here), and org-administrator standing
* is read from `sys_member.role`. Deactivating a position cannot empty either.
* `sys_user_permission_set` grants and from the deployment-config anchor (a
* declared `OS_PLATFORM_OWNER_EMAIL` address on a VERIFIED `sys_user` row,
* which `USER_STANDING_KEYS` below guards) — a position-bound
* `admin_full_access` reaches neither, in the resolver or here — and
* org-administrator standing is read from `sys_member.role`. Deactivating a
* position cannot empty any of them.
*/
export const PERMISSION_SET_STANDING_KEYS = ['name', 'active'] as const;

Expand Down
38 changes: 28 additions & 10 deletions packages/types/src/email-verified.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,34 @@
* column as verified would re-open the exact hole this predicate closes for
* every row that predates the column.
*
* ONE resolution, two consumers, by design (#12751): the walled
* platform-admin elevation gate (`plugin-security`
* `bootstrapPlatformAdmin`, where the check REFUSES an unverified owner
* match) and the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
* Those two must answer "is this row verified?" identically — a drift means
* a boot warning that forecasts a refusal the gate will not make, or stays
* silent about one it will. `@objectstack/types` is the shared home both
* packages already resolve `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
* ONE resolution, several consumers, by design (#12751) — and since the
* #11663 platform-admin re-anchor (leg L4) the walled platform-admin
* ELEVATION GATE this paragraph used to name first is RETIRED: under a
* walled posture `bootstrapPlatformAdmin` writes no grant row and elevates
* nobody, it reports. Standing is derived PER REQUEST instead — from a
* config-anchored verified email, or the legacy unscoped grant row — so the
* consumer set now includes the authorization derivation itself:
*
* - `matchesConfiguredPlatformAdmin` (`@objectstack/core`
* `security/platform-admin.ts`), read at the one derivation site
* (`resolve-authz-context.ts` §6b-config), where an UNVERIFIED account
* holding a declared address confers nothing — and, through it,
* `plugin-auth`'s last-admin guard, whose administrator enumeration must
* answer the same question the resolver does;
* - `resolvePlatformAdminStanding` (`plugin-security`
* `platform-admin-service.ts`), the read-only standing/audit answer the
* walled boot reports from, and `isVerifiedPlatformOwnerRow` beside it
* (`platform-owner-wall-bypass.ts`), the Layer 0 wall bypass;
* - the walled owner-verification boot diagnostic (`plugin-auth`
* `walled-owner-verification-path.ts`, where the check decides whether the
* declared owner's account is already past needing a verification path).
*
* They must all answer "is this row verified?" identically — a drift is no
* longer just a boot warning forecasting a refusal that will not be made, it
* is a diagnostic, an audit surface or a guard disagreeing with who actually
* resolves PLATFORM_ADMIN on the next request. `@objectstack/types` is the
* shared home every one of those packages already resolves
* `OS_PLATFORM_OWNER_EMAIL` from (`env.ts`).
*/
export function isEmailVerifiedUserRow(row: unknown): boolean {
const v = (row as { email_verified?: unknown } | null | undefined)?.email_verified;
Expand Down
Loading