Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.evidence.studio/llms.txt

Use this file to discover all available pages before exploring further.

Code-managed access is currently in private preview. To enable it for your organization:
Code-managed access lets you define who can view a project’s published reports in a single access.yaml file at the project root. The file lives alongside your content, ships through the same git workflow as your pages, and is enforced when readers visit your published reports. This is an opt-in alternative to the UI-based Page Level Access Control. When enabled for a project, the Share menu’s access controls are hidden — the yaml is the single source of truth.

Who can see your reports

Before you write any rules, it helps to know that an Evidence organization has two kinds of viewers:
  • Internal viewers — typical employees and teammates inside your organization. They are part of the org, hold a role of viewer or higher, and can be added to Groups.
  • External viewers / customers — clients or partners you share dashboards with from outside the company. They are managed under Customers and behave like a kind of group, but with one important difference: they are excluded from any “everyone in the org” rule.

When to use it

Use code-managed access when:
  • You want access rules to be reviewable and approved in pull requests alongside the content they protect, with the same review process you use for code changes
  • You manage many users and groups and prefer text edits over clicking through menus
  • You want to roll back access changes the same way you roll back code changes
  • You want a CI check to fail on invalid rules before they reach production
Stay on UI-managed access when:
  • A small group of admins maintains all access rules and the audit trail isn’t critical
  • You’re not yet using the GitHub two-way sync and don’t want a new file to maintain

The access.yaml schema

The file lives at the project root: access.yaml. Here is a complete example covering every supported construct:
project:
  grants:
    viewers:
      - $org # built-in: every internal org member with viewer or higher
      - alice@example.com # user (email)
      - marketing # group ID

pages:
  reports/q1-overview: # page path = directory slugs + file slug, no extension
    inherit: true # additive (default): project audience + grants below
    grants:
      viewers:
        - finance

  reports/internal:
    inherit: false # override: ONLY the grants below see this page
    grants:
      viewers:
        - alice@example.com
        - leadership
Page grants are additive by default. A page’s audience is the project audience plus anything listed under the page. To restrict access on a single page, set inherit: false — only the principals you list there will see that page.

Top-level keys

  • project — the project-wide audience. Required. Use project: {} for an admins-and-developers-only project.
  • pages — per-page overrides keyed by full page path. Optional. Pages not listed here inherit the project audience entirely.

viewers lists

The grants.viewers list defines who can see a project or page. It can contain four kinds of principals, mixed in any order:
  • Users — referenced by email, e.g. alice@example.com. Must resolve to an org member.
  • Groups — referenced by group ID, e.g. marketing. Group IDs are lowercase letters, digits, and hyphens. Create groups on the Groups page; a group’s ID is set at creation and cannot be changed, so existing references keep working even if the display name is renamed.
  • Customers — your external customer groups, referenced by their group ID just like internal groups.
  • $org — a built-in group meaning every internal member of your organization with viewer role or higher.
$org does not include customers. It grants access to every internal member of your organization with viewer role or higher, and nothing else. Customers must be granted access explicitly — either by email or by the customer group they belong to.
$org is project-level only. Using it under a page entry is rejected — to make a single page org-wide visible, leave inherit: true and grant $org at the project level.

inherit (pages only)

Controls whether the project’s viewers can also see this page:
  • inherit: true (default) — project viewers see this page, plus anyone you list under grants.viewers.
  • inherit: false — project viewers do not see this page. Only the principals you list under grants.viewers can see it.

Page paths

Use the full path within the project: directory slugs joined by /, then the file slug, no extension.
  • Valid: summary, reports/sales/monthly, q1-overview
  • Invalid: Reports/Sales (uppercase), /leading-slash, trailing-slash/, with spaces
Page paths must be lowercase, matching the form used in your published URLs.

Closed by default

To declare an admins-and-developers-only project, write an empty project: block:
project: {}
This is the minimum valid file. An entirely empty file, a comments-only file, or a file that omits the top-level project: key (for example, a pages-only file) is rejected by validation — see Validation below. We require the explicit project: declaration so that a forgotten or accidentally-truncated file fails loudly instead of silently locking your viewers out. To declare “open to the org”, you must write it explicitly:
project:
  grants:
    viewers:
      - $org

Examples

1. Open to the entire org

Every internal org member with viewer role or higher can see every page.
project:
  grants:
    viewers:
      - $org

2. Restricted to one group

The whole project is restricted to a single group. Useful for sensitive projects (finance, security, legal) where the audience is a tightly-defined team.
project:
  grants:
    viewers:
      - finance
Anyone outside the finance group (other than developers and admins, who always retain access) gets a 404 on every page.

3. Restricted to multiple groups + named individuals

Same pattern, but the audience is a few groups plus a couple of specific people not in any of them.
project:
  grants:
    viewers:
      - finance
      - leadership
      - alex@example.com
      - jordan@example.com
Lists can mix users, group IDs, and $org freely.

4. Open project, but one page is restricted

The project is open to the org, but a specific page (e.g. an executive dashboard or financial detail) is restricted to a smaller group. Use inherit: false so the project audience does not spill onto this page.
project:
  grants:
    viewers:
      - $org

pages:
  reports/board-meeting:
    inherit: false
    grants:
      viewers:
        - executives
Everyone in the org sees the project; only executives see reports/board-meeting.

5. Restricted project, with a few pages opened to a wider audience

The project is restricted to one group, but specific pages need a broader audience. Use inherit: true (the default) plus extra grants — the page audience becomes “the project’s audience plus these extras”.
project:
  grants:
    viewers:
      - finance

pages:
  reports/quarterly-summary:
    grants:
      viewers:
        - leadership
  reports/headcount:
    grants:
      viewers:
        - hr
        - leadership
finance sees every page (including the two listed). leadership additionally sees quarterly-summary and headcount. hr only sees headcount.

6. Per-customer page restrictions

When you publish customer-specific pages in the same project (e.g. an “Acme dashboard” and a “Globex dashboard”), pin each page to its customer with inherit: false. Leave the customer groups off the project-level grants — they only need to reach their own pages.
project:
  grants:
    viewers:
      - account-managers # internal team only

pages:
  customers/acme:
    inherit: false
    grants:
      viewers:
        - customer-acme
        - account-managers
  customers/globex:
    inherit: false
    grants:
      viewers:
        - customer-globex
        - account-managers
Each customer only sees their own dashboard. Account managers see both.

7. Shared customer dashboards

When all your customers see the same set of pages, list their customer groups at the project level.
project:
  grants:
    viewers:
      - customer-acme
      - customer-globex
      - account-managers # internal team

pages:
  internal-notes:
    inherit: false
    grants:
      viewers:
        - account-managers
Both customer groups and internal account managers see the project. Only account managers see internal-notes (the override hides it from customers).
If different customers see different pages or data in the same project, do not grant them at the project level — that would let every listed customer open every page. Use the per-customer page pattern above and grant each customer access only to their own pages with inherit: false.
Pair page-level access with Row-Level Security for true data isolation between customers. Code-managed access decides which pages a customer can open; Row-Level Security decides which rows of data they see when they query. For customer-facing reports where each customer should only see their own data, use them together: per-page access in access.yaml, RLS rules on the underlying tables.

Enabling code-managed access

  1. Open the project’s Settings page.
  2. Under Access management, click Enable code-managed access.
  3. Studio seeds an access.yaml in your working tree reflecting your project’s current grants.
  4. Open access.yaml in the editor, review it, and publish to activate.
Until you publish, the project still uses the existing UI-managed grants and the new file has no effect.

What happens at enable

  • The project switches to code-managed access.
  • The Share menu’s access controls are hidden across Studio — access.yaml becomes the single source of truth for who can view what.
  • A working copy of access.yaml is written to the project root.
  • Live validation activates in the editor (squiggles, autocomplete, the AI sidebar’s access-yaml awareness).
  • The GitHub PR check Evidence: access.yaml Validation runs on every PR that touches the project’s repo.
Existing feature branches need to merge in the default branch. Once access.yaml lands on your default branch, any feature branches that were open before enabling won’t have the file (or the new Share menu behavior). Have collaborators merge the default branch into their feature branches so the yaml is present and access changes flow through the file going forward.

Disabling

In Settings → Access management, click Disable code-managed access. The project reverts to UI-managed access, the Share menu reappears, and the grants currently in effect remain authoritative.
Disabling does not revoke grants that the yaml previously applied. The access state at the moment of disable becomes the new starting point. If you need to remove specific people, do so through the Share menu after disabling.
The yaml file is left in the repo when you disable — Studio ignores it until you re-enable. To remove the file entirely, delete it through Studio or via Git after disabling.

Validation

Studio validates access.yaml to make sure your access rules are well-formed and resolve against your org. Validation checks that:
  • The file exists and contains a top-level project: block (the minimum valid file is project: {})
  • The YAML parses and matches the expected schema
  • Every email refers to a real org member
  • Every group ID refers to a real group
  • Every page path refers to a real page
On feature branches we warn so you can stage work in progress. Before changes reach your default branch we block, so broken yaml can never affect real viewers.
SurfaceWhenOn failure
Editor liveEvery keystrokeInline squiggles, autosave proceeds
Studio commit on a feature branchOn commitWarn with dialog. Choose Commit anyway to land WIP, or fix first.
Studio commit on default branchOn commitBlock with dialog. No override.
Studio publish (merge feature → default)On publishBlock with dialog. No override.
GitHub PRPR opened, reopened, or new commits pushedCheck Evidence: access.yaml Validation fails with annotated lines
Default-branch merge appliedAfter mergeBanner + admin email; viewer access is paused until the failure clears

Failure recovery

If access.yaml is malformed or missing on the default branch after a merge, Studio cannot apply the new rules. The behavior is:
  1. Viewer access is paused. Until the next successful publish, only admins and developers can open the project. Viewers (internal and external) are blocked.
  2. Admins are notified. An email is sent to all organization admins, and a banner appears in Studio on every page until the failure is resolved.
  3. You have two recovery paths:
    • Fix the file: edit access.yaml to resolve the validation errors, commit, and merge. The next successful publish automatically restores viewer access.
    • Disable code-managed access: in Settings → Access management, click Disable code-managed access. The grants in effect immediately before code-managed access was enabled become authoritative again. You can re-enable later after fixing the file.
The strictness of the upstream validators means this state should be unreachable through normal use — the Studio commit/publish gates and the GitHub PR check all block invalid yaml before it can land. The failsafe exists for force-pushes, history rewrites, and unusual merge paths.

Branch behavior

You can use branches to preview access changes before they go live. Each branch uses its own access.yaml, so:
  • When you open a preview link for a branch, the audience is resolved from that branch’s access.yaml.
  • Changes on a feature branch do not affect the published access rules.
  • The rules only go live once the branch is merged into the published branch.
This lets you stage and review access changes the same way you stage and review content changes.

CI check on pull requests

When code-managed access is enabled and the project is connected to GitHub, every PR runs the Evidence: access.yaml Validation check alongside the existing Evidence: Markdown Validation check.
  • The check parses access.yaml from the PR head, validates schema, and resolves references against the project’s users, groups, and pages.
  • Errors appear as annotations on the offending lines in the PR file diff.
  • A missing access.yaml on a code-managed project fails the check.