Skip to content

Consolidate customer-facing quiltx (acl, bucket) into quilt3 #101

Description

@drernie

Move the customer-facing half of quiltx (ACL reconciliation and bucket
registration) into quilt3. Leave the operator half in quiltx at full velocity
(ECS, logs, shell, CloudFormation discovery, TLS overrides).

The boundary is "does a customer run it," not "is it fast or safe."

Design doc: proj/260827-quilt3-acl/DESIGN-quiltx-quilt3-consolidation.md
(owner: Simon Kohnstamm, assigned by Kevin 2026-08-20; bead qhq-4li3).
Status: proposed, not yet agreed.

Why now

quiltx is already in the production deploy path. The deployment branch
260506-coc-deployment installs a pinned quiltx and runs it as a deploy step:

# .github/workflows/tf-apply.yaml:100,143
pipx install 'quiltx==0.17.2'
quiltx catalog acl --catalog "$CATALOG" --yes default-acl.yaml

Nightly fails the deploy if ACL convergence fails, and ACL apply has delete
semantics — absence in the YAML means deletion. So the highest-blast-radius
operation we own runs behind the weakest gates in the org.

The open ACL PRs (quiltdata/deployment#2414, #2577) are the window to fix this
before the pattern sets, so both are parked pending this issue.

Scope

Moves into quilt3

Module LOC Tests Rationale
acl.py 3,359 122 Pure registry semantics, best-tested module, gates nightly deploys
bucket.py + tools/bucket.py 3,329 127 Cross-account onboarding is a customer/SA workflow; mutates customer AWS state
credentials, auth, identity, userconfig ~550 54 Folds into quilt3.session; removes duplicated credential minting
quilt_auth.py 313 14 Collapses to a small pre-session mint helper once inside quilt3

Stays in quiltx

Module LOC Rationale
ecs.py + tools/ecs/ 1,981 Needs stack-account AWS creds and the session-manager-plugin binary
logs.py 218 CloudWatch only, operator tooling
CFN discovery half of stack.py ~400 Requires AWS access to the stack account
tls.py 53 Invasive global monkey-patching

The Catalog object is the awkward middle. It is the right abstraction for
multi-catalog access and belongs in quilt3, but it currently also carries
cfn_client / aws_session / payload. Splitting it is the main refactor
this requires.

Findings from the analysis

  • quiltx does not use only public quilt3 APIs. It imports
    quilt3._graphql_client (quiltx/bucket.py:934, quiltx/stack.py:221),
    calls quilt3.admin.util.get_client(), and monkey-patches
    quilt3.session.get_registry_url (quiltx/quilt3_facade.py:89). Already
    coupled to quilt3 internals, just outside quilt3's CI.
  • Merge latency is ~2h apart, not a category difference. Median merged-PR
    cycle: quiltx 3.2h (n=40) vs quilt3 api/python 5.2h (n=7, directional).
    quilt3 CI wall clock is 3–6 min. No CODEOWNERS in quiltdata/quilt, so no
    named approver is structurally required.
  • quilt3's gates are genuinely heavier, and legitimately so. 10-way
    OS×Python matrix plus gendocs-check, testdocs, gql-check, against
    quiltx's single job on Python 3.14. The real friction is the
    regenerate-and-diff gates, not gatekeepers — worth reducing on their own
    merits.
  • No dependency-surface change. boto3 is already a hard quilt3 dependency
    (boto3>=1.21.7) and botocore ships all 434 service definitions in one
    package; sns, sqs, lambda, sts, cloudformation, ecs clients all
    construct in a clean quilt3==8.0.0 venv. Net new runtime deps from bucket:
    zero. From the credentials layer: keyring.

The real risk in bucket tooling

Not installation. Five calls mutate customer AWS account state:

  • put_bucket_policyquiltx/bucket.py:306
  • create_topic:334, set_topic_attributes:415
  • put_bucket_notification_configuration:885, :905

merge_bucket_policy (:280) is the one to read closely — a bad merge on a
live customer bucket policy is hard to reverse and can deny access.

This argues for the move: it is the highest-consequence code in either repo,
it runs behind one CI job today, and there is no moto anywhere in the test
suite
— policy-merge and notification-conflict logic is validated against
quiltx's own model of S3/SNS behavior rather than a simulator.

Live drift bug — fix regardless of the merge

quiltx declares quilt3>=7.3.0 with no upper bound and
requires-python = ">=3.9". Its lockfile resolves quilt3 7.3.0. quilt3
shipped 8.0.0 on 2026-08-04, which dropped Python 3.9. So
pipx install quiltx in deployment CI resolves a quilt3 version quiltx has
never tested against. The suite does pass on 8.0.0 (473 passed, 1 skipped) —
by luck, not verification.

Sequence

  1. Land Add a supported hook for overriding the registry URL without writing config.yml quilt#4878 — the supported registry-URL override hook.
    Filed 2026-05-04 offering a PR, zero comments in 3.5 months. Root cause of
    the monkey-patch; landing it deletes ~40 lines of quilt3_facade.py.
  2. Pin the ceiling in quiltx: quilt3>=8.0.0,<9,
    requires-python = ">=3.10", add the 3.10–3.14 matrix to quiltx CI.
    (No 3.11+ syntax in the codebase, so the 3.10 floor is safe.)
  3. Path-filter py-ci.yml in quiltdata/quilt. It currently fires ~34 jobs
    on a one-line change because nothing is path-filtered; the codegen workflow
    already does this correctly. Cuts friction without lowering a gate. Do this
    before asking anyone to move code.
  4. acl + bucket into quilt3 as separate PRs for reviewability (not separate
    releases). Keep quiltx catalog acl and quiltx bucket add as thin shims so
    tf-apply.yaml does not change on day one.
  5. Operator tooling stays in quiltx.

Add moto coverage for merge_bucket_policy and the notification-conflict path
during the bucket PR.

Open items

  • Branch protection settings are not visible in-tree. Merge-queue triggers in
    every workflow imply required status checks; confirm before assuming review
    requirements.
  • tls.py disables TLS verification process-wide with zero tests. Stays in
    quiltx under this plan, but worth fixing on its own merits.
  • tools/ecs/shell.py is 722 LOC with no dedicated test file.
  • Bus factor: one author holds 77 of 88 commits on code that gates nightly
    deploys. A resilience argument for consolidation.
  • Sequence with qhq-gmax (quilt3 arbitrary-GraphQL escape hatch). That
    primitive is what lets quiltx stop hand-writing GraphQL against
    _graphql_client.

Blocked PRs

  • quiltdata/deployment#2414 — Collab as Code: ACL bootstrap and SSO
    admin-password fix
  • quiltdata/deployment#2577 — Collab as Code: default-acl for open.quiltdata.com

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions