> ## Documentation Index
> Fetch the complete documentation index at: https://altostrat.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity and access

> How Studio authenticates users, derives short-term AWS credentials, isolates organizations, and enforces resource-level access — with the boundary between Clerk (identity) and Cognito (AWS authorization) explained.

Studio separates two concerns most apps blur. **Who you are** is Clerk. **What AWS calls you can sign** is Cognito. The two are wired together so a single Clerk session produces short-lived AWS credentials with the right organization context, and revoking your Clerk session immediately stops AWS calls from being signed.

This page walks through that flow, the organization isolation that sits on top of it, and the resource-level access controls that govern what you can see inside an org.

## The identity stack

| Layer             | Provider                                         | What it does                                                                                                      |
| ----------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| User identity     | Clerk                                            | Email, password, MFA, SSO (where configured), session lifecycle, organization membership.                         |
| AWS authorization | AWS Cognito Identity Pool                        | Exchanges a Clerk JWT for short-term AWS credentials scoped to the user's current organization.                   |
| API gateway       | AWS AppSync (GraphQL) + custom Lambda authorizer | Validates the Clerk JWT on every request, enforces organization membership, scopes resolvers to the caller's org. |
| Resource ACLs     | AppSync resolvers + DynamoDB row-level checks    | Enforce ownership, organization scope, custom share grants.                                                       |

## Sign-in flow

<Steps>
  <Step title="Sign in with Clerk">
    Studio opens a Clerk sign-in surface. Clerk handles password, MFA, SSO if configured by the org admin.
  </Step>

  <Step title="Receive a Clerk session">
    The Electron renderer holds the Clerk session. Studio requests JWTs from Clerk for the downstream services it needs to call, with the user's organization claim populated.
  </Step>

  <Step title="Exchange for AWS credentials">
    The Clerk JWT is exchanged with the Cognito Identity Pool for short-term AWS access credentials valid for the lifetime AWS sets.
  </Step>

  <Step title="Tag the credential with the organization">
    The Identity Pool's principal-tag mapping reads the organization claim from the Clerk JWT and attaches it as an AWS principal tag on every signed request.
  </Step>

  <Step title="Sign AWS calls">
    AppSync, KMS, and Bedrock calls are signed with the temporary credential. Server-side IAM policies and KMS key policies condition on the principal tag, so a credential issued for org A cannot read resources or decrypt material belonging to org B.
  </Step>

  <Step title="Refresh ahead of expiry">
    The desktop credential cache refreshes before the credential expires. A revoked Clerk session means the next refresh fails and AWS calls stop being signed within minutes.
  </Step>
</Steps>

## Why two systems instead of one

Clerk gives us first-class organization, role, and session management — including hosted MFA and SSO — without us having to operate it. Cognito Identity Pool is the only AWS-native way to convert a third-party JWT into short-term AWS credentials with attribute-based authorization. Wiring the two together means:

* We get the user-facing experience and security features of a dedicated identity vendor.
* We get AWS-native enforcement of organization scope at the IAM and KMS layers, not just at the application layer.
* A Clerk session revocation cuts AWS access at the next credential refresh — there is no long-lived AWS key to chase.

## Sign-out and revocation

<Steps>
  <Step title="User signs out">
    Clerk session is invalidated. Future Cognito refreshes for that session fail.
  </Step>

  <Step title="Local plaintext is purged">
    On the desktop, the sign-out routine purges every `vault:*` entry from the OS keychain, including cached plaintext data keys, and zeros the Go sidecar's in-memory copy.
  </Step>

  <Step title="Cached AWS credentials expire">
    The AWS credential cache holds the last issued credential until its natural expiry, typically within an hour. New requests cannot be signed after that.
  </Step>

  <Step title="Org admin can force-revoke">
    From the Clerk dashboard, an org admin can invalidate all sessions for a user (e.g., on departure). Combined with a [DEK rotation](./vault-and-keys), this guarantees the departed user cannot decrypt new envelopes even if they kept a copy of an old DEK.
  </Step>
</Steps>

## Organization isolation

Every record in Studio carries an `orgId`. Three layers enforce that boundary:

1. **AppSync custom Lambda authorizer.** Every GraphQL request hits a Lambda that validates the Clerk JWT, extracts the active `org_id`, and refuses requests where the caller's organization does not match the requested resource's organization.
2. **Resolver-level filters.** Every list/get/update operation is rewritten so the `orgId` filter is non-negotiable. Strict mode rejects any query that attempts to filter on a different `orgId`; lenient mode (used during the rollout) logs and rewrites.
3. **KMS key policy condition.** The per-organization customer master key in KMS will only decrypt for callers whose AWS principal tag `orgId` matches and whose `kms:EncryptionContext:orgId` matches the wrap. Even if a resolver or DynamoDB row leaked, decryption would fail.

The third layer is the one you should weight most heavily. Application-layer isolation can fail. Cryptographic isolation cannot — the failure mode is "you get garbage", not "you get someone else's data."

## Resource-level access inside an organization

Within an organization, four scopes apply to most resources (hosts, diagrams, procedures, memories, conversations, files):

| Scope        | Who can see it                                                  |
| ------------ | --------------------------------------------------------------- |
| Private      | Only the owner.                                                 |
| Org          | Every member of the organization.                               |
| Custom share | The owner plus a list of explicit members granted by the owner. |
| Inherit      | Resolved at read time from the parent folder's scope.           |

Custom shares are stored as `ResourceShareMember` rows with a role per member. Folder-inherited visibility resolves at read time so a folder change applies to all descendant items without a backfill.

The same scope mechanism applies to encrypted material. A custom share triggers the [resource DEK re-wrap](./vault-and-keys#cross-organization-shares) so the recipient's organization can decrypt the shared resource using its own KMS key, without exposing the originating org's DEK.

## The desktop sidecar's identity

The Go sidecar that runs SSH, packet capture, and other local operations does not have a separate identity to AWS. It runs in the same process group as the Electron parent, inherits the same operating-system trust, and is reached only over a localhost loopback bound to the parent's PID. AWS-side calls always originate from the renderer process with the user's short-term credentials.

This is a deliberate choice. Adding a second identity for the sidecar would expand the attack surface without adding meaningful protection — the sidecar already holds plaintext keys in memory at the moments when the user authorized it.

## Federation and SSO

SSO is configured at the Clerk layer per organization. Clerk supports SAML and the major OIDC providers (Microsoft Entra, Google Workspace, Okta). When SSO is in place:

* The Clerk session lifetime is governed by the org's SSO policy.
* MFA is the SSO provider's MFA, not Clerk's.
* Sign-out propagates from the SSO provider to Clerk to Studio's AWS credential cache.

Org admins should treat SSO as the right default for any production deployment.

## Related

<CardGroup cols={2}>
  <Card title="Vault and keys" icon="key" href="./vault-and-keys" arrow="true" cta="Read">
    Where the per-organization KMS keys live and how they enforce isolation cryptographically.
  </Card>

  <Card title="Audit and telemetry" icon="bar-chart" href="./audit-and-telemetry" arrow="true" cta="Read">
    What's logged about authentication and authorization events.
  </Card>
</CardGroup>
