Skip to content

control-plane: Snapshot authorization model and retryable staleness error (1/7) - #3341

Closed
bbartman wants to merge 11 commits into
masterfrom
bmb/2781-stack-1-snapshot-authz
Closed

control-plane: Snapshot authorization model and retryable staleness error (1/7)#3341
bbartman wants to merge 11 commits into
masterfrom
bmb/2781-stack-1-snapshot-authz

Conversation

@bbartman

@bbartman bbartman commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

Split 1 of 4 of #3155 (issue #2781): the foundation layer for moving catalog
authorization out of SQL and onto the in-memory authorization Snapshot.

  • validation: adds Error::AuthorizationSnapshotStale { catalog_name }
    the retryable signal that an authorization denial was evaluated against a
    Snapshot which may not yet reflect a committed grant — and
    is_authz_snapshot_stale() to classify it after anyhow wrapping.
  • control-plane-api Snapshot authorization model (server/snapshot.rs):
    • Authorization enum (Authorized / Denied / Stale) with
      ok_or_stale(), which converts a provisional denial into the retryable
      error above.
    • Snapshot::resolve_authorization(), user_authorization(),
      role_authorization() — grant evaluation against the pinned Snapshot,
      classified by whether the Snapshot postdates the operation's freshness
      anchor (taken_after, allowing TEMPORAL_SKEW).
    • Snapshot::spec_capabilities() — in-process replacement for the
      SQL-computed spec_capabilities column, used to render "Available grants
      are:" error messages.
    • STALE_RETRY_WAKE, the re-poll interval used by later splits.
  • Rename App::snapshotApp::snapshot_watch, ahead of follow-ups
    where executors pin per-poll Snapshot tokens distinct from the watch.

This PR is purely additive: nothing consumes the new surface yet.

Tests

Unit tests in server/snapshot.rs (no DB required):

  • test_resolve_authorization — the three-way classification, including the
    temporal-skew boundary.
  • test_spec_capabilities — insta snapshots of capability rendering against
    Snapshot::build_fixture.
  • test_taken_after_allows_for_temporal_skew.

Stack

  1. → this PR — Snapshot authorization model + retryable staleness error
  2. control-plane, agent: move catalog authorization in-process against a pinned Snapshot (2/7) #3342 — move authorization in-process against a pinned Snapshot
  3. agent: publications executor defers on stale authorization snapshots (3/7) #3343 — publications executor defers on stale snapshots
  4. agent: discovers executor authorizes data-planes via Snapshot and defers on staleness (4/7) #3344 — discovers executor authorizes via Snapshot and defers on staleness

…able staleness error

Adds validation::Error::AuthorizationSnapshotStale and is_authz_snapshot_stale()
as the retryable signal that an authorization denial was evaluated against a
Snapshot which may not yet reflect a committed grant.

Adds the in-process authorization surface to Snapshot: the three-way
Authorization enum (Authorized / Denied / Stale) with ok_or_stale(),
user_authorization / role_authorization over the snapshot's grants,
spec_capabilities() for error-message rendering, and STALE_RETRY_WAKE.

Also renames App::snapshot to App::snapshot_watch, ahead of follow-ups where
executors pin per-poll Snapshot tokens distinct from the watch itself.

This PR is purely additive; nothing consumes the new surface yet. Split 1 of 4
from #3155.
@bbartman
bbartman force-pushed the bmb/2781-stack-1-snapshot-authz branch from cf94b28 to 96ea0b5 Compare August 11, 2026 18:23
@bbartman bbartman changed the title control-plane: Snapshot authorization model and retryable staleness error (1/4) control-plane: Snapshot authorization model and retryable staleness error (1/7) Aug 12, 2026
@bbartman

Copy link
Copy Markdown
Contributor Author

Note that this combines what was previously two PRs #3155 and #3300

Alex-Bair and others added 9 commits August 12, 2026 12:07
`build:rocksdb` passed PORTABLE=0, which RocksDB reads as `-march=native`,
so librocksdb.a -- and every binary linking it -- took its instruction
floor from whichever machine compiled it. One master build drew an
AVX-512 runner and produced a flowctl that SIGILLs on any host without
AVX-512, breaking most estuary/connectors CI jobs. The same library goes
into the reactor and control-plane images, three of which deploy
automatically from Platform Build.

This commit pins haswell on x86_64, the level we had already been shipping:
reactor:v0.6.13-11-gd9006db953c has zero AVX-512 instructions under RocksDB
symbols, and the same source line compiles to vinserti128 there and
vinserti64x2 after. Note: we should avoid x86-64-v3, which lacks the
PCLMUL that RocksDB's crc32c fast path needs, and PORTABLE=1, which sets
no -march at all. aarch64 adds no -march under either setting, so it is
unchanged.
The default was raised from 5m to 20m in d09cb56 (June 2025), but three descriptions of it were left behind: the ShardTemplate doc comment, its generated entry in flow.schema.json, and the hand-written table in the Configuring Task Shards page.

No behavior change. The 20 minute default in assemble is intentional and unchanged; only the text describing it is corrected.

flow.schema.json is edited in place rather than regenerated, because the released flowctl predates syncSchedule and regenerating with it would drop valid schema. The edited string is byte-identical to what an in-tree regeneration emits.
…eld (#3355)

BYOC customers enrolled in AWS's Migration Acceleration Program need a
cost-allocation tag (e.g. map-migrated) applied to every AWS resource of
their data-plane, including hosts est-dry-dock replaces over time via
Pulumi's provider default_tags.

data-plane-controller re-serializes data_planes.config into the Pulumi
stack config with no serde catch-all, so a field added only on the
est-dry-dock/Pydantic side would be silently dropped before Pulumi ever
sees it. This adds the Rust side of that field so it survives the
round trip; it must ship and deploy before the est-dry-dock change.
…d gotcha (#3272)

The firstWriteWins/lastWriteWins page linked ./#reduction-guarantees (itself)
instead of ../#reduction-guarantees (the reduction-strategies overview page,
where that heading actually lives). With the only broken anchor site-wide now
fixed, flip onBrokenAnchors from warn to throw so future broken anchors fail
CI instead of shipping silently.

Also documents the pre-existing hubspot-real-time redirect collision: it only
reproduces on macOS's case-insensitive filesystem and doesn't affect the
Linux-based production build, so it's a local-dev note rather than a bug fix.
…3220)

Google is removing gsutil from the default gcloud CLI bundle after March 2027;
gcloud storage is the supported replacement.
…3233)

* docs: clarify sync schedule connector scope and backfill heuristic

Sync schedules are used by warehouse connectors AND file/object-store
connectors (S3/GCS/Azure Blob file sinks, Iceberg), not just warehouses.
Transactional databases (Postgres, MySQL, SQL Server) and streaming/API
destinations do not use them.

Also document how a connector distinguishes catching-up from backfilling
(recent transaction sizes) so the delay-skip behavior during backfills is
explicit.

* modify language on upload interval connectors

---------

Co-authored-by: aeluce <emily@estuary.dev>
…able staleness error

Adds validation::Error::AuthorizationSnapshotStale and is_authz_snapshot_stale()
as the retryable signal that an authorization denial was evaluated against a
Snapshot which may not yet reflect a committed grant.

Adds the in-process authorization surface to Snapshot: the three-way
Authorization enum (Authorized / Denied / Stale) with ok_or_stale(),
user_authorization / role_authorization over the snapshot's grants,
spec_capabilities() for error-message rendering, and STALE_RETRY_WAKE.

Also renames App::snapshot to App::snapshot_watch, ahead of follow-ups where
executors pin per-poll Snapshot tokens distinct from the watch itself.

This PR is purely additive; nothing consumes the new surface yet. Split 1 of 4
from #3155.
@github-actions

Copy link
Copy Markdown

🚀 Preview deployed to https://docs.estuary.dev/pr-preview/pr-3341/

@jwhartley

Copy link
Copy Markdown
Contributor

Docs have moved, and this PR straddles the split. The code belongs here; the
doc files no longer do.

estuary/flow's site/ tree is no longer published. docs.estuary.dev is
served from estuary/docs (platform docs, under content/), which aggregates
connector pages from estuary/connectors (under docs/reference/Connectors/)
at build time.

Suggested split:

  • Keep the code changes in this PR and drop the doc files from it.

  • Open the doc half against estuary/docs, where these paths map across:

    • site/docs/features/configuring-task-shards.md becomes content/features/configuring-task-shards.md
    • site/docs/getting-started/installation.md becomes content/getting-started/installation.md
    • site/docs/guides/customize-dataflows/materialization-sync-schedule.md becomes content/guides/customize-dataflows/materialization-sync-schedule.md

Two notes on the non-doc site/ files in this PR, because neither ports
cleanly:

  • The onBrokenAnchors: 'throw' flip is a real improvement and it is still
    wanted. estuary/docs carries the identical onBrokenAnchors: 'warn' line
    and the same TODO(johnny) comment, so the anchor-checking gap you closed
    here is still open on the published site. Worth reopening against
    estuary/docs docusaurus.config.js. Expect it to surface real broken
    anchors on first run.
  • The site/README.md macOS note is already solved differently in
    estuary/docs: its docusaurus.config.js detects Darwin and filters the
    case-colliding hubspot-real-time redirect out at build time, so the local
    build does not fail there. That note does not need to move.

Flagging it because the doc half would otherwise merge into a tree nobody
serves. The "docs.estuary.dev: Deploy" check will still go green, which is
deliberate (it keeps flow's gh-pages rollback artifact current until
2026-09-30) and is not a signal that the doc change shipped.

Context: migration announcement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants