← Design · c136

prior-art.md

c136 Phase 0: prior art

Use this file to check the grant model in plan.md against how seven others let an outsider into a customer's system: AWS, Google Cloud, Azure, GitHub Apps, Tailscale, the break-glass pattern, and the vendor-support grants at Okta and Salesforce (with Kolide's Honest Security for the words). Each section says what the thing is, lays its grant model out in the same eight rows, then says what we copy and what we refuse, in our terms (the rules R1 to R7 and the defaults D1 to D7 in the plan). The last three sections test our model against theirs, draw the implications for Phases 1 and 2, and list the questions with a default each.

Every source was read on 2026-11-11. The URL stands on its own line under the claim it supports. This session's network allowed search excerpts of the documentation pages but not the pages themselves; the numbers that matter for the partner page (Phase 4) are listed at the end for a second reading from a laptop.

1. AWS: support roles, session duration, and AWS's own access

What it is. In AWS, access is a role: a bundle of permissions with a trust policy that says who may assume it, and every use is a session with temporary credentials. AWS's own support engineers reach a customer's account through one such role, AWSServiceRoleForSupport, which AWS creates in every account and which the customer cannot remove without an Enterprise Support plan.

Grant modelAWS
Who grantsThe account's administrator writes the role and its trust policy. For AWS's own access, nobody: the service-linked role is created with the account.
To whomA principal: an account, a role, a user, or the support.amazonaws.com service, never a named person.
ScopeThe role's permission policies. AWS Support's role reaches resource metadata, not customer data; fields that could carry data are redacted.
Duration and expiryA session: 15 minutes to the role's maximum, which the administrator sets between 1 and 12 hours (default 1 hour). The role itself never expires. Role chaining caps a session at 1 hour.
Approval stepsNone at use time. The trust policy is consent given in advance.
What the grantee seesThe policy JSON, and whatever the console or API returns.
Audit recordCloudTrail: every API call, with the assumed-role session name. AWS Support's own calls are visible there too.
RevocationEdit the trust policy, or deny every session issued before a point in time (the "revoke active sessions" policy). AWS's own role: deleted on request through a Technical Account Manager, Enterprise Support only.

The facts behind the table.

Copy.

  • The session as the unit of time, under something longer. AWS separates the role (what may be done) from the session (one bounded use of it). Our grant is the longer thing and the mechanic's login sessions are the shorter: a grant of three days holds several sessions, each of which ends on its own. Phase 1 should model both, so that "3 actions so far" can also say "in 2 sessions".
  • Every call carries the session's name. CloudTrail's assumed-role session name is the precedent for D5: each audit entry carries the grant id, and the person, with no extra step by the mechanic.
  • Metadata, not data, by default, with redaction named. AWS says in one sentence what Support cannot see and gives the example. Our Observe level does the same: "no event payloads unless the scope names them" is that sentence; the partner page should give the example.
  • The off switch for the vendor's own access. AWS lets an Enterprise customer remove its support role entirely. R7 is stricter and simpler (a plane with no reachability has no grants at all), but the idea that the partner can turn the door off, not only close it, belongs on the partner page.

Refuse.

  • A role that never expires. The AWS role is standing; only the session ends. R2 says every grant ends. We do not build a standing "Qpoint support role" on the plane with short sessions under it; we build grants that expire and sessions under those.
  • A service principal instead of a person. support.amazonaws.com is who acts in CloudTrail; the engineer is invisible to the customer. R4 names the person.
  • Access the customer did not open. AWS Support's role exists in every account from day one, and only Enterprise customers can remove it. R1: the partner grants, Qpoint never holds standing access, on any plan.
  • Consent as policy JSON. The trust policy is precise and unreadable. R6 wants the grant said in sentences; the JSON (our model as data) sits behind them, not in front.
  • Twelve hours as a ceiling. It is sized for automation and console days, not for a fix that takes three days. Our window is in days, our sessions in hours.

2. Google Cloud: Access Transparency and Access Approval

What it is. Access Transparency is a log of what Google's own staff do to a customer's content, with the reason for each access; Access Approval, built on it, makes Google ask the customer before such an access and lets the customer approve, dismiss, or later invalidate the request. Both are opt-in controls, enrolled per service and per organisation, folder, or project.

Grant modelGoogle Cloud
Who grantsA customer administrator holding the Access Approval approver role; invalidation needs a separate invalidator role.
To whomGoogle personnel, unnamed. The log identifies them by employer, job category, and physical location, not by name.
ScopeThe enrolled services; each request names the resource and the locations it will be accessed from.
Duration and expiryThe request carries a requested expiration; the approver picks the expiration time; access runs from approval to that time. An unapproved request stays denied and is dismissed automatically after 14 days.
Approval stepsA request arrives by email (or Pub/Sub); the approver approves or dismisses in the console or through the API; approvals can be signed with the customer's own Cloud KMS key. The customer can allow only customer-initiated-support reasons.
What the grantee seesThe Googler sees whether the request was approved. The customer sees the resource, the reason code and its detail (a case number), the locations, and the requested expiry.
Audit recordAccess Transparency log entries: resource, action, time, reason, the access-approval ids, an event id tying the access to its incident, and the actor's employer, job category, and location. The approval decisions are audit-logged.
RevocationInvalidate the approved request; access under other active approvals stays.

The facts behind the table.

Copy.

  • A structured reason plus the detail. CUSTOMER_INITIATED_SUPPORT plus "Case Number: 142" is exactly our purpose category plus the partner's own sentence. Phase 1 writes the purpose as an enum and the sentence as text, and adds an optional ticket reference as its own field (question 6).
  • Requested against granted. Google records what Google asked for (expiry, locations) and what the customer gave. Our grant should carry both the requested window and the granted one, so the record shows the admin shortening a request (question 7).
  • The approval id on every log line. Access Transparency entries carry the access-approval ids; ours carry the grant id (D5). Same shape.
  • Restrict to customer-initiated reasons. The customer can refuse every Google-initiated reason at the policy level. R1 makes this our only mode: there is no Qpoint-initiated reason code at all. Say so on the partner page.
  • Publish the exclusions. Google states which accesses bypass approval. Ours are none, and that sentence ("no Qpoint access to your plane happens outside a grant") is worth more printed than assumed (question 8).
  • Invalidate's small print as a warning. Revoking one approval leaves others standing. Our revoke must end every session of every person under the grant, at once, and a plane with two grants open must say so on the screen.

Refuse.

  • The unnamed accessor. Google tells the customer the employer, the job category, and the country. R4 names the person; the partner's audit log says "Tyler", not "Qpoint, engineering, US".
  • Visibility only in the log product. Transparency after the fact, in Cloud Logging, is R5's floor, not its ceiling. The web app shows the grant live ("3 actions so far"); the summary at close comes to the admin, not to a query.
  • Opt-in, tier-gated, dependency-chained. Access Approval needs Access Transparency, which needs a support tier. Every plane has grants, with no switch to find and no tier to buy.
  • Fourteen days pending. A request that nobody answers for two weeks is a request nobody wanted. Ours expires unanswered in a day (question 10).
  • Dismiss as a silent deny. Google's "dismiss" leaves the requester to infer. Ours is one word, "declined", with an event, and the mechanic is told.

3. Azure Customer Lockbox

What it is. Customer Lockbox puts the customer in the approval path when a Microsoft engineer, working a support request, needs just-in-time access that would reach the customer's data. The engineer's request lands with the customer's designated approver by email and in the portal; approved access lasts the time the request states and ends by itself.

Grant modelAzure (and Microsoft 365)
Who grantsA subscription Owner, a Global administrator, or a holder of the dedicated "Azure Customer Lockbox Approver for Subscription" role; in Microsoft 365, the "Customer Lockbox access approver" role.
To whomThe Microsoft engineer on the support ticket. The request names the ticket, the resource and the justification.
ScopeThe resource named in the request; subscription-scoped or tenant-scoped.
Duration and expiryThe engineer's request states the duration and the customer sees it before approving. An older Azure page caps it at 4 hours; Fabric and Power Platform state 8 hours; Microsoft 365 caps at 4 hours. An unanswered request expires: four days in Azure, 12 hours in Microsoft 365.
Approval stepsOne approver, one decision: approve or deny, from the email or the portal.
What the grantee seesJust-in-time access to the named resource for the stated time.
Audit recordThe subscription's Activity Log (subscription-scoped) or the Entra audit log (tenant-scoped), with operations for approve, deny, and expiry; Microsoft 365 writes to its unified audit log.
RevocationAutomatic at expiry. In Power Platform, an approved request "can't be revoked for the entire duration of the access period".

The facts behind the table.

Copy.

  • The mechanic writes the request; the partner grants. Lockbox is request-first: the engineer states the ticket, the resource, the justification and the duration, and the customer only decides. Our "requested" state is this (question 5); the request pre-fills the grant screen so the admin reads and grants rather than composes.
  • The duration is on the request, in front of the approver, before the click. Nothing is approved without its end time visible. Our grant screen shows the window as a date and time, not a duration ("until Thursday 14:00", as the plan's honest state already says).
  • A dedicated approver role. Lockbox separates "may approve vendor access" from Owner. D2 names the org admin; Phase 3 should let a plane name a smaller set of admins who may grant (question 2 touches this).
  • Three audit operations with plain names. Approve, deny, expiry: three verbs an auditor can filter. Our access.grant.* family is the same idea with a fourth verb for the actions in between.
  • The exclusions said out loud. Microsoft states when Lockbox does not apply. Ours is "never", and we print it (question 8).

Refuse.

  • Approved means unrevocable. Power Platform's rule breaks R5: revocation is one click and immediate, always.
  • Hours as the whole window. Four or eight hours suits a ticket touch, not a fix. A three-day fix under Lockbox is a chain of requests. Our window is sized to the job, with the short defaults doing the work Lockbox's cap does.
  • Four days in the queue. A request waiting four days is stale by the time it is answered. One day (question 10).
  • A break-glass path around the grant. Microsoft's outage exclusion is the one thing a partner will ask us about. Qpoint has none: a hot-fix is a grant the partner opens, with a one-hour default, and the only break-glass on a plane is the partner's own (section 6).
  • An add-on. Lockbox is a feature of higher plans. The grant is the only door, on every plane.

4. GitHub App installation screens

What it is. A GitHub App is a machine identity that an organisation owner installs with a fine-grained permission set, chosen resource by resource (contents, issues, metadata, members) at a level (read, read and write, admin), on all repositories or a chosen few. The installation screen lists every permission as a sentence, and when the app later asks for more, each installing owner is asked again.

Grant modelGitHub Apps
Who grantsAn organisation owner, or a repository administrator for their own repositories; other members see "Request" and an owner decides. Sensitive permissions (all organisation-level ones, repository administration, repository creation) always need an owner.
To whomThe app, acting as itself. Its developer is not a party to the installation.
ScopeA level per resource, and all or selected repositories.
Duration and expiryThe installation has no expiry. Each installation access token lasts one hour and can be narrowed to fewer repositories and permissions at creation.
Approval stepsOne screen, one click. New permissions requested later need a fresh approval from each installing owner; until then the old set stands.
What the grantee seesThe installer sees the sentences and the repository chooser. The app sees its installation and permissions through the API.
Audit recordThe organisation audit log records the installation, permission changes, suspension and removal; the app's own actions show as the app.
RevocationSuspend the installation (temporary) or uninstall it; remove repositories from it, which cuts the token's reach at once.

The facts behind the table.

Copy.

  • Level plus resource, as a sentence. "Read access to metadata" is the model for R6: a verb-less level ("Read", "Read and write") and the thing it touches. Our three levels are three such sentences with the resources named (section 9 drafts them).
  • A grant that grows is a new consent. When the ask changes, the owner is asked again and the old grant stands meanwhile. R2's "a renewal is a new grant" is the same rule in time; GitHub gives us the rule in scope. Raising a level on an active grant is a new grant, never an edit.
  • All or selected. The repository chooser is our scope chooser: the whole plane, or named parts. Default to the smaller choice when the purpose allows it (R3).
  • Suspend as a state of its own. Suspended is not uninstalled: the record and the configuration stay, the access stops. Our "revoked" keeps the grant's record and summary; "closed" is the end of the window. Two states, as the sketch has them.
  • A short token under a long installation. One-hour tokens under an open-ended installation are the same shape as sessions under a grant (section 1).

Refuse.

  • No expiry on the installation. GitHub's grant lasts until someone remembers it. R2.
  • An app instead of a person. The audit log says "dependabotbot". R4 wants "Tyler".
  • A list that scrolls. Installation screens routinely list ten permissions. Three levels, each in one sentence, is the whole screen; if a fourth sentence is needed, the model is wrong (D6).
  • A request with no clock. "Request" waits on an owner indefinitely. Ours expires (question 10).

5. Tailscale: the admin console, sharing, and PAM

What it is. Tailscale's admin console has a role set for who may change what (Owner, Admin, Network admin, IT admin, Billing admin, Auditor), node sharing lets a machine be shared with a named user on another tailnet, and the new Tailscale PAM (beta, from the Border0 acquisition in March 2026) adds just-in-time access to a specific service for a stated time, approved in Slack, with session logs and recordings. There is no documented way for Tailscale's own staff to enter a customer's tailnet.

Grant modelTailscale
Who grantsOwners and Admins set roles; a device's owner or an admin shares a node; a PAM approver answers a request.
To whomA named user identity, including one on another tailnet (sharing). Tailscale staff: nobody; the only documented support path is recovering admin access by proving domain ownership with a TXT record.
ScopeRoles: areas of the console (the Auditor reads configuration and users, writes nothing). Sharing: one machine, quarantined by default (it may be reached from the other tailnet, it cannot reach out). PAM: one service or resource.
Duration and expiryRoles and shares have no expiry. PAM access is scoped to a time period and expires by itself ("Access will automatically expire in 3 hours").
Approval stepsA share is an invitation the recipient accepts. PAM: request, approval in Slack.
What the grantee seesThe shared machine inside their own tailnet, shown as shared by the sharer; the PAM user sees the approval and its expiry.
Audit recordConfiguration audit logs for console changes; PAM session logs and, for supported protocols, recordings.
RevocationUnshare the node; remove the role; PAM access expires or is revoked.

The facts behind the table.

Copy.

  • The Auditor role is Observe. "Reads everything, changes nothing" exists as a product role with a name and a recommended audience. Our Observe level is that role on a plane, for a window.
  • Quarantined by default. A shared node can be reached but cannot reach out. The grant's scope should have the same property: the mechanic reaches the named parts of the plane and nothing beyond them, in particular not the endpoints that report to it (clarifying question 3, default plane only).
  • A named identity across organisations. Sharing admits a user from another tailnet under their own identity, shown as shared by the sharer. D3's named Qpoint identity on the partner's plane is this shape, and the audit entry can say both who acted and who let them in.
  • The expiry in the approval sentence. "Access will automatically expire in 3 hours" is the honest state said at the moment of grant. Ours says it on the grant screen, in the c137 notice, and in the native app's Status line.
  • Session recording as a Change-level option. PAM records sessions for supported protocols. Shell access at Change level (D4) could log commands; recording is a question for the partners (question 9).

Refuse.

  • Shares and roles with no end. A share stays until someone unshares. R2.
  • Approval in Slack, record elsewhere. The decision must live on the plane with the grant (D1), and the notice goes through c137's channel. Slack can carry the notice; it cannot hold the grant.
  • No door at all. Tailscale has no vendor-access path, which is the right default (R7) but not an answer for a partner who asked us to fix something. The grant is the door; "no grants" is its resting state.
  • Device lifetimes as windows. Node key expiry is a device-lifecycle setting, not a job window. Our window is the job's.

6. Break-glass patterns

What it is. Break-glass is pre-authorised emergency access for the moment normal access fails: in Microsoft Entra, two cloud-only emergency accounts excluded from the policies that could lock everyone out, monitored so that every use raises an alarm. Its disciplined cousins are just-in-time elevation (Entra Privileged Identity Management, AWS's TEAM), where a named person activates a pre-approved role for a bounded time with a reason, a ticket, and sometimes an approver.

Grant modelBreak-glass (Entra) · JIT elevation (PIM, AWS TEAM)
Who grantsNobody at the time: the organisation pre-authorises. PIM and TEAM: an approver per role or eligibility policy, optional.
To whomBreak-glass: a shared emergency account, not a person. PIM and TEAM: a named, eligible user.
ScopeBreak-glass: everything. PIM: one role. TEAM: an account and a permission set.
Duration and expiryBreak-glass: until the credentials are rotated. PIM: an activation of 1 to 24 hours. TEAM: the requested time, under a global cap the administrator sets.
Approval stepsBreak-glass: none; the procedure is written down in advance. PIM: MFA, a justification, ticket information, and an approver if configured. TEAM: a ticket number and an approver group per policy.
What the grantee seesThe role active, with its end time.
Audit recordBreak-glass: an alert on every sign-in. PIM: the activation with justification and ticket. TEAM: request details and session activity, viewable by requester, approver, and auditor.
RevocationRotate the emergency credentials; deactivate the role; TEAM removes access automatically.

The facts behind the table.

Copy.

  • Hot-fix is our break-glass, kept inside the grant. The pattern's three disciplines transfer whole: the shortest window (one hour by default, raised by the admin), the loudest record (every hot-fix grant notifies the plane's admins through c137 when it opens and again at close), and a written procedure tested on a schedule (the grant path exercised quarterly on a lab plane, so the first real hot-fix is not the first time).
  • Eligible, then active. PIM and TEAM separate who may be let in from who is in. The named Qpoint people on a grant are the eligible set; a session under the grant is an activation. Phase 1 models both.
  • Justification and ticket as two fields. PIM asks for a reason and a ticket; the ticket is "information-only". Ours: the purpose and the partner's sentence are required, the ticket reference optional (question 6).
  • Alert on every use. The break-glass rule "a high-priority alert every time" becomes, for Change-level grants, a notice on every session start, not only at open and close (question 11).

Refuse.

  • Shared accounts. The emergency account is deliberately nobody's. R4 and R1 together forbid a shared Qpoint account on any plane, in any emergency.
  • Exclusion from policy. Break-glass works by standing outside Conditional Access. The grant goes through the same door and the same policies as the partner's own admins (D4); what it changes is who the door admits, for how long.
  • A ticket nobody checks. PIM's "not enforced" ticket is honest about itself. Ours is optional, and the audit entry shows it exactly as typed, so the partner can check it against their own tracker.
  • Access that bypasses the grant in an outage. Microsoft's own services do this (section 3). Qpoint never self-grants, incident or not; if the partner cannot open a grant because the plane is down, the plane is down for us too, and the fix is the partner's break-glass, not ours.

7. Vendor support on the customer's clock: Okta and Salesforce, with Kolide for the words

What it is. Okta and Salesforce both let the customer switch on the vendor's own support access for a time the customer chooses, from one control: Okta's "Give access to Okta Support" checkbox grants read-only impersonation for a support case, extendable a day at a time; Salesforce's "Grant Account Login Access" dropdown grants the administrator or Salesforce Support login as the user for one day to one year. Kolide's Honest Security, which c137 already cites for end-user messages, supplies the tone for the sentences on the grant screen: explain, then ask.

Grant modelOkta · Salesforce
Who grantsOkta: an org administrator, per support case. Salesforce: each user for their own account (administrators can widen this with login access policies).
To whom"Okta Support", "Salesforce Support", or the customer's own administrator: the vendor, tied to a case, not a named engineer.
ScopeOkta: the whole org, read-only, as an administrator would see it. Salesforce: the user's own account, exactly as the user sees it.
Duration and expiryOkta: 24 hours per the help page (8 hours in the API), extended by 24 hours at a time, not stackable. Salesforce: 1 day, 3 days, 1 week, 1 month, or 1 year.
Approval stepsOne checkbox, or one dropdown.
What the grantee seesOkta: the admin console, read-only. Salesforce: the application as the user.
Audit recordOkta's System Log: impersonation grant, extend, revoke, initiate, end. Salesforce audits actions taken while logged in as another user.
RevocationOkta: clear the checkbox, immediate. Salesforce: set the dropdown to "No Access".

The facts behind the table.

Copy.

  • One control is the whole grant screen. Okta's checkbox and Salesforce's dropdown are the simplest grant screens in this document, and partners already know them. Ours is one screen with four fields (purpose, level, scope, window) and the people, and nothing else.
  • Read-only is the design, not a setting. Okta Support's impersonation is read-only by construction. Observe is our default (R3) and the admin raises it; the partner page says Observe is what most grants will be.
  • Durations in the partner's words. "1 day, 3 days, 1 week" is how Salesforce's users pick, and it is how Mark said it ("three days"). The window picker offers 1 hour, 1 day, 3 days, 7 days and nothing finer (plan).
  • Extend as its own event, and not stackable. Okta's extend is explicit, logged, and bounded. R2 keeps renewal as a new grant; the UI can still offer "Open a new grant like this one" in one click, with its own record (question 12).
  • The five verbs. grant, extend, revoke, initiate, end is a complete lifecycle in one event family. Ours (D5: opened, action, revoked, closed) should add the request and the session start, and say "expired" inside closed (question 13).
  • Explain, then ask. Kolide's tenets, applied to an administrator rather than an end user: the grant screen explains what each level allows in a sentence the admin can verify, states the consequence, and then asks. No "are you sure"; the sentence is the surety.

Refuse.

  • The vendor as the actor. "Okta Support" and "Salesforce Support" are who appear. R4 names Tyler.
  • Impersonation. Logging in as the user makes the record say the user did it. Under D3 the mechanic acts as themselves, under the grant, and the audit line names both the person and the grant.
  • A year. Salesforce's longest option, and a vendor's request for "at least one month", are what R2's seven-day ceiling exists to prevent. Longer work is several grants, each with its own record and close summary.
  • Two numbers for one thing. Okta's help page says 24 hours and its API says 8. The grant model is data in one place (Phase 1), and every surface reads it; a duration that appears in a sentence is computed from the record, never typed twice.

Our model against theirs

The five tests from the plan, against each precedent. "Thinner" means the precedent carries something our model does not yet; "stricter" means ours demands more.

PrecedentFour purposesThree levelsSeven-day windowNamed peopleOne event family
AWSNone; an AWS role has no purpose field. Ours is stricter.Levels are policies, unbounded in number; Support's own is "metadata only". Ours is stricter (three) and thinner (no redaction list yet).Sessions of 1 to 12 hours under a role with no end. Ours is stricter on the role, looser on the session (none modelled yet).A service principal. Ours is stricter.CloudTrail, one stream, session name on every call. Equal; ours adds the grant id.
GoogleReason codes plus detail: the same shape, with more codes (Google-initiated ones). Ours is stricter (customer-initiated only).None: a request is for a resource, not a level. Ours is stricter.Approver-chosen expiry, no documented ceiling; 14 days pending. Ours is stricter on both.Employer, job category, country. Ours is stricter.Access Transparency plus the approval audit, two products. Ours is stricter (one stream). Thinner: no signed approval, no requested-versus-granted expiry.
Azure LockboxA ticket and a justification, free text. Ours is stricter (an enum).None; the request names a resource. Ours is stricter.Hours, stated per request; four days pending. Ours is looser on the window (days), stricter on pending.The engineer on the ticket; the customer sees the request, not a roster. Ours is stricter.Approve, deny, expiry in the activity log. Equal; thinner: we have no "declined" event yet.
GitHub AppsNone. Ours is stricter.Read, read and write, admin, per resource: the closest cousin. Ours is stricter (three, whole-plane) and thinner (no per-resource level; scope does that work).No expiry; tokens of 1 hour. Ours is stricter.An app. Ours is stricter.The organisation audit log. Equal; thinner: no "re-consent when the ask grows" event, which ours needs as "a new grant replaces this one".
TailscaleNone; PAM requests name a resource and a time. Ours is stricter.Console roles (Auditor is Observe); no Operate or Change equivalent. Ours is stricter.Roles and shares without end; PAM in hours. Ours is stricter on roles, looser than PAM.Named users across tailnets. Equal.Configuration audit logs plus PAM session logs and recordings. Thinner: no session recording, no session events.
Break-glass, PIM, TEAMA justification and a ticket. Ours is stricter (an enum) and thinner (no ticket field).One role per activation. Ours is stricter (three named levels).1 to 24 hours (PIM); a configurable cap (TEAM); break-glass has none. Ours is stricter than break-glass, looser than PIM.Named (PIM, TEAM); a shared account (break-glass). Ours is stricter than break-glass.PIM audit history; TEAM session activity; alerts on every break-glass use. Thinner: no alert on each session start.
Okta, SalesforceNone (a case id at Okta). Ours is stricter.Read-only only (Okta); the user's own view (Salesforce). Ours is stricter (three) and the same at the default.8 or 24 hours plus a day at a time (Okta); 1 day to 1 year (Salesforce). Ours is stricter than Salesforce, looser than Okta.The vendor. Ours is stricter.Five impersonation events (Okta). Thinner: no request, session-start or extend event.

Where ours is stricter, on every row: the partner grants and the vendor never holds anything (R1); every grant ends inside seven days (R2); the person is named (R4); one event family in the plane's own stream (D5); revocation is immediate everywhere (R5), where Power Platform refuses it. No precedent does all five; the nearest are Okta (customer-switched, read-only, revocable, logged as a family) and Google (reason codes, approval ids on every entry).

Where ours is thinner, and should not stay so:

  1. No session under the grant. AWS, GitHub, PIM and Okta all have a short-lived thing under the long-lived thing. Phase 1 adds the session (one login of one named person under one grant) as a record and as events.
  2. No request record from Qpoint's side. Lockbox, Google and Okta are request-first; the plan's sketch has "requested" as a state but D5 has no event for it. Phase 1 adds the request, its expiry, and "declined".
  3. No ticket field. Google, PIM, TEAM and Lockbox carry one. Add it, optional, shown verbatim.
  4. No requested-versus-granted window. Google records both. Add both.
  5. No exclusions statement. Google and Microsoft print theirs. Ours is "none", and the partner page prints it.
  6. No per-session notice at Change. Break-glass alerts on every use. Change-level sessions notify on start (question 11).
  7. No session recording. Tailscale PAM has it. A question for the partners, not a Phase 1 feature (question 9).

Implications for Phases 1 and 2

The model as data (Phase 1). The grant in the plan, with the additions this reading earned:

RecordFieldsFrom
grantid; plane; purpose (diagnose · fix · implement · hot-fix); reason (the partner's sentence); ticket (optional, verbatim); level (observe · operate · change); scope (whole plane, or named parts); window: requested (start, duration), granted (start, end, at most 7 days), with defaults by purpose (diagnose 1 day, fix 3 days, implement 3 days, hot-fix 1 hour); people (named Qpoint identities, at least one); requested_by (a Qpoint person, or none when the admin opens it unasked); granted_by (the admin); second_approver (optional, Change level, off by default); state (none · requested · active · revoked · closed); close (reason: expired · revoked · completed; summary: actions, sessions, people, first and last action)plan; Google (reason code and detail, requested and granted expiry); Lockbox (request-first); PIM and TEAM (ticket); D2
sessionid; grant id; person; started; ended; actionsAWS sessions under roles; GitHub tokens under installations; PIM activations; Okta initiate and end
event, access.grant.*requested · declined · opened · session.started · action · session.ended · revoked · closed, each carrying the grant id and the person; closed carries the reason and the summaryD5; Okta's five verbs; Lockbox's three; Google's approval ids on every line

Adding a purpose or a level stays a cycle decision (D6). Every sentence a surface shows is computed from this record; no number is typed twice (the Okta lesson).

The sentences (R6). Modelled on GitHub's "level plus resource" and Kolide's "explain, then ask". Product-UI tone: concise, functional, calm; no exclamation points; no "are you sure".

WhereSentence
Level: ObserveQpoint can read this plane's configuration, logs, metrics and audit log. It cannot change anything, and it cannot read event payloads unless the scope names them.
Level: OperateQpoint can read what Observe allows, restart services, run shipped migrations and change settings. It cannot deploy code.
Level: ChangeQpoint can do what Operate allows and deploy a build or a hot-fix. Shell access is limited to the plane's own containers. The shortest default window.
Purpose: DiagnoseLook, change nothing. Observe level, one day.
Purpose: FixFix a documented problem. Name the ticket. Three days.
Purpose: ImplementBuild a feature you asked for. Three days.
Purpose: Hot-fixResolve an incident in progress. One hour. Every session notifies your admins.
Request (from Qpoint)Tyler asks for Operate access to fix ticket 142, for three days. Grant · Change · Decline. This request expires tomorrow 09:00.
Grant screen, before the clickQpoint (Tyler, Kamal) will have Operate access to this plane until Thursday 14:00. Every action is recorded under grant 1f3a and you can revoke it at any moment.
Active (web app)Qpoint has access to this plane until Thursday 14:00 (fix · operate). 3 actions so far, by Tyler.
Active (native Status line)Qpoint has access to this plane until Thu 14:00 (fix · operate).
Revoke controlRevoke access now. Qpoint's sessions end immediately; the record stays.
RevokedQpoint's access was revoked by Dana at 11:20. 3 actions in 1 session; the list is in the audit log under grant 1f3a.
ClosedQpoint's access closed Thursday 14:00. 12 actions in 2 sessions, by Tyler and Kamal; the list is in the audit log under grant 1f3a.
NoneNothing. The Status line is empty; the web app's grants page lists past grants and one control: Open a grant.

The mock (Phase 2). The grant screen is the request pre-filled (Lockbox), one level chosen by its sentence (GitHub), the window as a date and time (Lockbox), the people by name (Tailscale sharing), and one control (Okta). The five states are five stories: none, requested, active, revoked, closed with summary. The Status line story in c131 shows active and none, nothing else (D7).

Questions

The plan's four, then what the reading raised. Each with a default that holds until Tyler or a partner says otherwise.

  1. Are the four purposes the words partners use, or do they think in "incident", "change request", "support case"? Default: keep the four; ask two partners before Phase 1. The reading supports the enum (Google's reason codes, Lockbox's ticket plus justification) and found no vendor using a verb set like ours, so the partner test is the only evidence that matters.
  2. Should the Change level need two admins (D2)? Default: off, with the field in the model. Google's signed approvals and Lockbox's dedicated approver role suggest a lighter rule first: a plane names which admins may grant at all, and Change inherits that list.
  3. Does a grant ever reach an endpoint machine, or only the plane? Default: plane only. Tailscale's quarantined share is the precedent: reachable, not reaching.
  4. Do the contracts need a line that mirrors the levels? Default: yes, later, with Rob. AWS's and Microsoft's documentation does the contractual work in product terms; the partner page (Phase 4) is drafted so that Rob can quote it.
  5. Who starts a grant: Qpoint's request, or the partner unasked? Default: both. A request is an event and pre-fills the screen (Lockbox, Google, Okta); an admin can also open a grant with no request (Salesforce). The record says which.
  6. Does the grant carry a ticket id apart from the sentence? Default: yes, optional, shown verbatim in every audit entry (Google, PIM, TEAM); never validated against the partner's tracker (PIM's honesty about that).
  7. Can the admin shorten or lower what Qpoint asked for? Default: yes; the grant records requested and granted (Google). Raising is a new grant, never an edit (GitHub).
  8. Is there any Qpoint access to a partner's plane that does not go through a grant? Default: none, and the partner page says so in one sentence, next to the list of what the plane sends to Qpoint on its own (telemetry, update checks), which is a separate c134 question. Google and Microsoft publish their exclusions; ours is the empty list, printed.
  9. Session recording at Change level? Default: no in Phase 1. Shell sessions at Change log every command with the grant id; screen or terminal recording (Tailscale PAM) waits for a partner to ask.
  10. Does a request expire unanswered? Default: yes, after one day, with a declined event whose reason is "expired". Azure gives four days, Microsoft 365 twelve hours, Google fourteen days; a day is long enough for an admin's working day and short enough that nobody grants a stale request.
  11. Does every session under a hot-fix or Change grant notify the admins, or only open and close? Default: every session start, for hot-fix and Change (the break-glass rule); open and close only, for the rest. Through c137, at normal delivery.
  12. Renewal: a new grant, or an extend? Default: R2 stands, a new grant with its own record. The UI offers "Open a new grant like this one" from an active or closed grant, pre-filled (Okta's extend, kept honest).
  13. Which events are in the family? Default: requested · declined · opened · session.started · action · session.ended · revoked · closed, with closed carrying expired, revoked, or completed as its reason. Four more than D5 lists; agreed with Tyler and Kamal in Phase 3.

Sources (all read 2026-11-11)

Read through search excerpts of the pages named above; this session's network did not allow the pages themselves (docs.aws.amazon.com, docs.cloud.google.com, learn.microsoft.com, docs.github.com, tailscale.com, help.okta.com, help.salesforce.com, honest.security). Two pages are cited from memory and marked so: the IAM revoke-sessions procedure and Tailscale's configuration audit logs.

Numbers to re-read from a laptop before Phase 4: Azure Lockbox's current access cap (4 or 8 hours) and queue (four days); Microsoft 365's 4-hour cap; Google Access Approval's 14-day dismissal and its exclusions list; Okta's 8 or 24 hours; Salesforce's exact duration list.

https://docs.aws.amazon.com/awssupport/latest/user/using-service-linked-roles-sup.html · https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSSupportServiceRolePolicy.html · https://repost.aws/knowledge-center/athena-query-cloudtrail-logs-support · https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html · https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html · https://repost.aws/knowledge-center/iam-role-chaining-limit · https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_revoke-sessions.html · https://docs.cloud.google.com/assured-workloads/access-transparency/docs/overview · https://docs.cloud.google.com/assured-workloads/access-transparency/docs/reading-logs · https://docs.cloud.google.com/assured-workloads/key-access-justifications/docs/justification-codes · https://docs.cloud.google.com/assured-workloads/access-transparency/docs/release-notes · https://docs.cloud.google.com/assured-workloads/access-approval/docs/overview · https://docs.cloud.google.com/assured-workloads/access-approval/docs/approve-requests · https://docs.cloud.google.com/assured-workloads/access-approval/docs/reference/rest/v1/organizations.approvalRequests/invalidate · https://docs.cloud.google.com/assured-workloads/access-approval/docs/access-control · https://docs.cloud.google.com/php/docs/reference/cloud-access-approval/latest/V1.ApproveDecision · https://learn.microsoft.com/azure/security/fundamentals/customer-lockbox-overview · https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/security/fundamentals/customer-lockbox-overview.md · https://learn.microsoft.com/fabric/security/security-lockbox · https://learn.microsoft.com/power-platform/admin/about-lockbox · https://learn.microsoft.com/purview/customer-lockbox-requests · https://www.microsoft.com/en-us/microsoft-365/blog/2015/04/21/announcing-customer-lockbox-for-office-365/ · https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app · https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/limiting-oauth-app-and-github-app-access-requests-and-installations · https://github.blog/changelog/2026-10-13-github-app-improvements-for-least-privilege-and-management/ · https://docs.github.com/en/apps/using-github-apps/reviewing-and-modifying-installed-github-apps · https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation · https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps · https://tailscale.com/docs/reference/user-roles · https://tailscale.com/blog/admin-roles · https://tailscale.com/docs/features/sharing · https://tailscale.com/docs/features/declarative-node-sharing · https://tailscale.com/docs/privileged-access-management/what-is-tailscale-pam · https://tailscale.com/use-cases/pam · https://tailscale.com/tailscaleup-date-week-26 · https://www.networkworld.com/article/4215616/tailscale-expands-from-vpn-into-a-full-connectivity-platform.html · https://tailscale.com/blog/jit-access-ga · https://tailscale.com/docs/use-cases/infrastructure-access/manage-least-privileged-and-jit-access · https://tailscale.com/docs/reference/messages/console/no-access · https://tailscale.com/kb/1203/audit-logging · https://learn.microsoft.com/entra/identity/role-based-access-control/security-emergency-access · https://learn.microsoft.com/entra/architecture/security-operations-privileged-accounts · https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-how-to-change-default-settings · https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings · https://aws-samples.github.io/iam-identity-center-team/ · https://aws-samples.github.io/iam-identity-center-team/docs/guides/admin.html · https://aws.amazon.com/blogs/security/temporary-elevated-access-management-with-iam-identity-center/ · https://help.okta.com/en-us/content/topics/settings/settings-support-access.htm · https://support.okta.com/help/Documentation/Knowledge_Article/Admin_Resources/How-do-I-grant-Okta-Support-access-to-my-Org · https://developer.okta.com/docs/api/openapi/okta-management/management/tags/orgsettingsupport · https://support.okta.com/help/s/article/read-only-impersonation-access-system-logs-audit-events?language=en_US · https://www.salesforcetutorial.com/grant-login-access-administrators-salesforce-com/ · https://sfplugin.com/salesforce-login/grant-support-access/ · https://support.veeva.com/hc/en-us/articles/360005884093-How-to-Grant-Login-Access-in-Salesforce · https://help.salesforce.com/s/articleView?id=000383726&language=en_US&type=1 · https://honest.security/ · https://github.com/kolide/honest.security · https://www.kolide.com/blog/what-is-honest-security-and-why-is-it-important

Qpoint Brand Style Guide