Commercial colleagues may hold logins. What they get is a different application, not this one with the interesting parts locked, because a lock is itself a disclosure: a greyed-out control tells the person in front of it that something exists and that somebody else can read it.
Those three links are this view. The masthead above them belongs to the medical application and is present because this demo serves one application rather than two, so today only the URL separates the surfaces. Every explanation on this page is addressed to a reviewer: a built commercial view would carry the sections and not the argument about them.
An identity provider is configured and this browser carries no session. Signing in shows this screen.
Behind this: the lists and the activity counts this account holds. No request was sent, so nothing on this screen is a guess about whether the service is up.
No request was sent for these counts either, for the reason above.
SampleNothing below is a measurement.
No route in this API is role-aware. require_roles is defined at apps/api/src/skepsis_insights_api/deps.py:51 and no route depends on it, skepsis_platform.auth.principal.ROLES carries no commercial member by decision, and there is no export route of any kind. The picker below is the shape of a control and not a control, and its columns are the four NP-11 names.
Check it: grep -rn require_roles apps/api/src returns one line, its own definition. GET /api/gates?open_question=OQ-35 returns the one requirement quoted below.
Every export would be logged with the user, the time and the content (NP-11, ACC-04). No such log exists on this deployment, because no export does.
ACC-02, the field the ledger calls blocked, on the export rule:
Nothing. The same rule governs export: a commercial user exports fields built from public sources only, such as papers, trials, congress roles and affiliations, and every export is logged with user, time and content (NP-11).
Verdict BUILD, basis research. Read from GET /api/gates?open_question=OQ-35 on this request, not typed into this screen.
This is the part a demo is tempted to fake, by adding a word to a list and switching to it. The word would not survive the request: an unknown role maps to viewer on both sides, so a screen claiming one authority would sit over a database enforcing another.
| Roles a token can carry | customer_adminkol_leadfield_medical_leadmslviewer |
|---|---|
| Roles the decisions name | ACC-03 names five: KOL lead, field medical lead, Medical Science Liaison, commercial and administrator. Four of them are above. The fifth is the one this page is for, and principal.py declines to add it, on the ground that inventing the role answers OQ-35 in code. |
| Routes that read a role | None. require_roles is written and called by nothing, so every route in this API scopes by account and none by role. |
ACC-02, the field the ledger calls buildable, on what the separation has to be:
All of it. Commercial users may hold logins, in a separate view that keeps consented signals and medical content out (OQ-35). Every user carries a role, and the filter is applied to the data rather than to the screen: a commercial role sees no signal- derived field, no fit score and no evidence answer, anywhere, including through the API.
Verdict BUILD, basis research. Read from GET /api/gates?open_question=OQ-35 on this request, not typed into this screen.
Absent from the product, not from this view
Nothing signal-derived, no fit score and no evidence answer is fetched, held or named here, and no control implies one. That part is structural. The rest is not yet: the two routes above would answer a commercial token with the same bytes they answered this one, because there is no commercial token for them to answer. The decision is taken and written down, and the filter sits on the screen where ACC-02 asks for it on the data.