loopable / platform /core /platform_admin.py
fsanyoto's picture
Deploy AIOS web (React glide grid + FastAPI slice)
ea7b176 verified
Raw
History Blame Contribute Delete
3.65 kB
"""core/platform_admin.py β€” THE PLATFORM-OPERATOR PREDICATE (wave 19, owner item 13 / ruling R3).
There are now TWO kinds of administrator in this product and they must never be confused:
* a **tenant admin** (`role: 'admin'`) runs ONE company's workspace β€” its accounts, its
keychains, its databases. Nurilab's admin is one; Royal's is one. `core.perms.is_admin`
is that wall and it is scoped to the caller's own tenant everywhere it is used.
* a **platform admin** operates LOOPABLE ITSELF β€” the cross-tenant view of who our customers
are, what they are running, and what it costs. That is a different question and it needs a
different key, because every tenant already has an admin and none of them may see the others.
β›” THE DOUBLE LOCK, and why it is two conditions and not one (R3, verbatim: "NEW fail-closed
`platform_admin` server predicate (tenant-scoped `is_admin` does NOT qualify)"):
record flag `platform_admin is True` AND `tenant == 'loopable'`
Either half alone is a promotion path we do not want to exist. The flag alone would mean a
tenant admin who can write user records (Y4's `POST /admin/users` is reachable by every tenant
admin) could mint themselves a cross-tenant reader inside their OWN company. The tenant alone
would mean every future account in the `loopable` workspace β€” a designer, a contractor β€” reads
every customer's operational data by virtue of their email domain. Requiring both means the
promotion needs a write to a record AND membership of a tenant that no customer's admin can
create accounts in.
FAIL-CLOSED IN THE STRICT SENSE: `is True`, not truthiness. A record carrying the string
"false", a 0, a "yes", or a partially-read dict is NOT a platform admin. The flag is absent on
every pre-wave record, which is the correct answer for all of them.
⚠ THE FLAG MUST RIDE `users._public()` OR THIS PREDICATE IS BLIND. `deps._user_for` builds every
API session from that projection, so a field that lives only on the stored record is invisible
to every route that asks this question β€” the same rule `core.users` states for `perms`/`perms_v`
("the wall travels on this projection or it does not travel"), recurring on a new field. Both
sides land in the same change, and `verify_api.py`'s W19-ADMIN section drives the predicate
through a real SESSION rather than through a hand-built dict, so a dropped projection is red.
This module deliberately holds NO routes, NO store reads and NO imports of the permission layer:
it is one question, answerable from the session's own user dict, callable from either host.
"""
#: The ONE tenant slug a platform administrator may belong to. A constant rather than an env var
#: on purpose β€” "which company operates this platform" is not a per-deployment setting, and an
#: env-var reader here would be one misconfigured container away from admitting another slug.
PLATFORM_TENANT = 'loopable'
def is_platform_admin(user):
"""True iff `user` is a Loopable platform operator. Fail-closed on anything else.
`user` is the PUBLIC session projection (`core.users._public`) or a raw record β€” both carry
the same two keys, so the predicate answers identically wherever it is asked. None, {}, a
non-dict, a missing flag or a mismatched tenant are all False, and none of them are an error:
"not a platform admin" is the answer for almost every session the product will ever serve.
"""
if not isinstance(user, dict):
return False
if user.get('platform_admin') is not True:
return False
return str(user.get('tenant') or 'royal-imports').strip().lower() == PLATFORM_TENANT