| """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. |
| """ |
|
|
| |
| |
| |
| 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 |
|
|