Skip to content

[Provider plugins S2] Sentry observe/project provider and credential separation #72

Description

@AntoineToussaint

Outcome

Create the Sentry reference provider as the observe/project-only
counterexample and prove:

  • a provider can be useful without remote mutation or callback;
  • regional/self-hosted origins use host admission safely;
  • secret-bearing read responses are filtered before provider code;
  • browser-public, runtime-public, setup-secret, and build-secret values remain
    correctly separated;
  • the setup credential never becomes runtime configuration.

Sentry runs in parallel with Resend after the Stripe baseline.

Dependencies and parallelism

Provider foundation must be green:

Stripe baseline:

Sentry may proceed in parallel with the Resend provider once Stripe opens the
v0 baseline.

The protocol is not declared stable until Stripe, Sentry, and Resend all pass
the cross-provider contract matrix.

Repository ownership

This bootstrap issue is tracked in codefly-dev/module-saas-starter because
codefly-dev/provider-sentry does not yet exist.

Deliverables:

  1. create codefly-dev/provider-sentry;
  2. implement provider code/tests/docs there;
  3. migrate starter Sentry setup and dogfood;
  4. generic Core/CLI defects get cross-linked provider-neutral fixes only.

Operational prerequisites

Keep inside this issue:

  • dedicated Sentry test organization/project;
  • controlled project-read setup credential;
  • optional isolated org:ci build credential;
  • CI secret channel;
  • known project with one and then multiple client keys for ambiguity tests;
  • controlled frontend/backend error generation;
  • release/source-map test path and cleanup/rotation procedure.

Default CI uses cassettes/conformance, not live Sentry.

Scope

Inputs

  • API origin:
    • Sentry default;
    • US region;
    • DE region;
    • explicitly admitted self-hosted origin;
  • organization slug;
  • project slug;
  • optional explicit client-key ID;
  • setup credential handle (project:read);
  • public DSN expected value where operator supplies one;
  • environment/release configuration;
  • optional build credential reference/handle (org:ci);
  • output configuration names:
    • runtime/browser error-tracking;
    • optional build-only error-tracking-build.

No webhook/callback/ingress input is required.

Origin admission

Use host origin policy:

  • manifest declares Sentry defaults/patterns;
  • binding selects exact origin;
  • host admits exact scheme/host/port;
  • origin is shown in Plan and bound into handle/digest;
  • private self-hosted destination requires explicit governed admission;
  • wrong-region redirect must not carry credentials;
  • credentialed redirects remain disabled.

Qualify actual wrong-region behavior live; do not assume redirects or errors.

Credential roles

Setup:

  • bearer token with project:read or stronger project scope only where
    explicitly accepted;
  • used for project and client-key observation;
  • never projected.

Build:

  • separate org:ci credential for releases/source maps;
  • optional;
  • host-to-host projection only;
  • distinct build configuration/consumer;
  • never frontend/backend runtime;
  • do not claim arbitrary token-scope introspection if Sentry does not expose
    it.

Runtime/browser:

  • public DSN only;
  • no management token.

Project-management credential:

  • out of v0.1 because project creation has side effects and conditional
    organization scope.

Observed resources

sentry.project:

  • exact organization/project identity;
  • safe project fields;
  • status/platform where relevant;
  • origin/region;
  • accessibility.

sentry.client-key:

  • cursor-complete list;
  • key ID;
  • active/revoked state;
  • public DSN;
  • safe rate metadata;
  • no secret fields.

Selection:

  1. explicit configured client-key ID wins if active and project-owned;
  2. otherwise exactly one active eligible key;
  3. zero active -> BLOCKED/MANUAL_ACTION;
  4. multiple active -> BLOCKED/MANUAL_ACTION with safe IDs;
  5. never select array[0];
  6. stable repeated observation produces no diff.

Doctor reports revocation/rotation/ambiguity and supplied-DSN mismatch.

Secret-bearing read response

Sentry's client-key response can place:

  • secret;
  • dsn.secret;

beside dsn.public.

Manifest response policy must:

  • allow only safe ID/status/public DSN fields;
  • SUPPRESS_REPORT_PRESENCE for both legacy secret locations across arrays;
  • drop undeclared fields;
  • canonicalize before provider/log/cassette;
  • fail closed on moved/renamed/unparseable required fields.

Only dsn.public reaches provider code. Raw legacy secret bytes must be absent
from provider process, log, state, plan, receipt, diagnostic, cassette, and
Git.

Plan/actions

V0.1 is observe/project only:

  • VALIDATE;
  • OBSERVE;
  • NOOP;
  • PROJECT_OUTPUT;
  • BLOCKED;
  • MANUAL_ACTION;
  • DISCONNECT.

No remote CREATE/UPDATE/DELETE/IMPORT ownership is claimed.

PROJECT_OUTPUT is still an explicit approved host action. This proves the
same Plan/Apply/commit path works when there is no remote mutation.

error-tracking@1 output

Public/browser/runtime:

  • ERROR_TRACKING_MODE=sentry;
  • NEXT_PUBLIC_ERROR_TRACKING_MODE=sentry;
  • public DSN for browser;
  • same public DSN for backend SDK;
  • Sentry environment;
  • organization/project identifiers where contract permits;
  • release identifier where configured.

Sentry documents DSNs as safe to expose publicly. The generic contract must
mark DSN PUBLIC and browser-exposable, while still avoiding unnecessary
generic CLI display.

Build-only:

  • optional SENTRY_AUTH_TOKEN reference in a distinct
    error-tracking-build configuration;
  • consumer class build only;
  • never injected into frontend/accounts runtime.

Setup token is not output at all.

Scope diagnostics

Be honest:

  • project/client-key endpoints require project read/write/admin;
  • org:ci is appropriate for CI/release/source-map work;
  • Organization Auth Token endpoint coverage/scope introspection may not be
    fully documented;
  • report purpose fit as verified/unverified rather than inventing scope
    introspection;
  • qualify whether sntrys_ organization token can access project-read
    endpoints in live acceptance.

Rate limits

Normalize:

  • per-caller + endpoint windows;
  • concurrent request limits;
  • documented Sentry rate headers;
  • retry/reset metadata.

Observation/Doctor must be bounded and avoid aggressive polling.

Future mutation pressure test

Do not implement project creation in v0.1.

Add a documented/pure design pressure test for:

  • project creation;
  • client-key create/rotate/revoke;
  • auto-created personal-team side effect;
  • project:write and conditional org:write;
  • capture/output timing;
  • replacement/rotation.

The purpose is to identify protocol assumptions hidden by an observe-only
provider, not to expand scope.

SaaS Starter migration

Replace scripts/setup/sentry.sh with a thin non-writing shim only after
parity.

Do not port the current single-token conflation.

The shim:

  • maps safe org/project/origin/token-file/reference inputs;
  • creates/updates no remote resource;
  • performs no curl/configuration writes;
  • explains separate setup and build credential purposes;
  • translates to codefly provider setup error-tracking;
  • hard-fails unsafe/obsolete flags with remediation.

Required tests

Tier 0

  • regional/self-hosted origin schema;
  • project/client-key observation mapping;
  • complete pagination;
  • explicit key selection;
  • zero/multiple active ambiguity;
  • public DSN classification;
  • setup/build/runtime separation;
  • PROJECT_OUTPUT-only plan;
  • no-mutation capability;
  • build configuration consumer isolation;
  • error/rate mapping;
  • shim static/flag behavior.

Tier 1 cassettes

  • project retrieval;
  • multi-page client keys;
  • client response containing poison secret and dsn.secret;
  • public DSN only in filtered provider response;
  • auth/project/scope/not-found/wrong-origin/rate-limit cases;
  • zero/one/multiple/revoked keys;
  • schema drift/moved secret -> fail closed.

Scan provider input/output, cassette, log, diagnostic, state, receipt, and
projection for poison setup/legacy secrets.

Tier 3 live Sentry

  • default/US/DE selected origin;
  • wrong-region behavior;
  • self-hosted admission if a test instance exists (otherwise contract test);
  • project-read setup token;
  • qualify sntrys_ project endpoint coverage;
  • complete key list and selection;
  • create/rotate an additional test client key manually to prove ambiguity;
  • revocation/rotation drift;
  • rate-limit header normalization where safely triggerable;
  • optional org:ci build credential;
  • reviewed sanitized cassettes.

Tier 4 starter dogfood

  • provider setup performs no remote mutation;
  • public DSN reaches browser and backend;
  • controlled browser error appears in test project;
  • controlled backend error appears;
  • environment/release correlation works;
  • optional source maps/build release use build-only credential;
  • setup token absent from running frontend/accounts environments;
  • build token absent from runtime;
  • second setup/plan no diff.

Security invariants

  • Setup token never becomes output.
  • Build token is separate and build-only.
  • Runtime/browser receive only public DSN/configuration.
  • Legacy client-key secret fields never cross broker boundary.
  • Binding-supplied origin is explicitly host-admitted.
  • Observe/project provider cannot express a mutating request.
  • Ambiguous client keys block instead of selecting arbitrarily.
  • No Sentry branch in Core/CLI.

Acceptance criteria

  • codefly-dev/provider-sentry exists and passes provider conformance.
  • Setup works against dedicated project without remote mutation.
  • US/DE/custom origin admission is exact and plan-bound.
  • Cursor-complete deterministic key selection handles zero/multiple/revoked
    keys safely.
  • Poison legacy secret/dsn.secret values are absent from every provider
    and persisted surface.
  • Public DSN is actually available to browser/backend.
  • Setup credential is absent from all runtime/build outputs.
  • Optional build credential appears only in the authorized build consumer.
  • Controlled frontend/backend/release dogfood succeeds.
  • Second plan is empty.
  • Starter script is a non-writing shim.
  • Sentry's non-webhook/observe-only shape passes the cross-provider matrix.

Explicit non-goals

  • Sentry project/team/organization creation.
  • Client-key creation/rotation automation.
  • Inbound Sentry webhook.
  • Production mutation.
  • Arbitrary Sentry resource IaC.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthighHigh-priority autonomous implementation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions