All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
quiltx catalog api-keyprints the storedqk_...API key for a catalog, with--newto mint, store, and print a replacement. Supports browser-based login or--username/--passwordU/P bootstrap, plus--insecurefor localhost testing.quiltx catalog loginmints and stores a catalog API key during the auth flow so downstream tools can reuse it without re-authenticating.
quiltx ecs logs --set-level LEVELupdatesQUILT_LOG_LEVELon the registry service via a new task definition revision and forced deployment;--reset-levelremoves the override. Auto-discovers stack, cluster, service, and container.quiltx ecs statusshows or waits for ECS service rollout status (primary deployment, running/desired counts, recent events). Supports--waitwith timeout.
- Moved log viewing under the
ecsgroup:quiltx logsis nowquiltx ecs logs. The old top-levellogscommand has been removed. - Centralized stack/context resolution in
quiltx.stack: catalog lookup, stack discovery, region selection, and ECS resource extraction now follow one shared path acrosscatalog,ecs, andbucketcommands. Read-only commands auto-discover the stack payload; mutating commands auto-discover then fail with explicit remediation when required fields are missing. ecs logstruncation floor raised to 160 characters so long log lines remain readable.
quiltx catalog aclaccepts arbitrarysso.<claim>selectors, not onlysso.groups, and emits SSO JSON Schema mappings for scalar or array-valued custom claims.
quiltx catalog acluses role and policy IDs from fetched state when updating or deleting existing resources, avoiding quilt3 name-as-ID lookup failures that surfaced as opaqueInternal Server ErrorGraphQL errors.quiltx catalog aclnow detaches users, SSO mappings, policy associations, and policy role associations before deleting roles or policies, allowing stale managed roles and inline policies to be removed cleanly.- GraphQL error formatting no longer repeats identical wrapper and nested messages such as
Internal Server Error: Internal Server Error.
quiltx catalog aclactually dedupes(bucket, level)now:_permissions_for_bucketsdrops READ when the bucket is also inread_write. Previously emitted both rows and tripped the registry's composite PK onRolePolicyBucketPermission(role_policy_id, bucket_name)as an opaque 500 frompolicyCreateManaged/policyUpdateManaged.quiltx catalog aclskips the SSO update (with a clear warning) when pruning orphaned roles would dropdefault_role. Previously the pruned payload was sent withoutdefault_roleand the registry rejected it withInvalidInput: config.default_role: field required—SsoConfig.default_roleis a required pydantic field.quiltx catalog aclpolicy create / update / delete warnings now refetch state and append[desired: ...; server now: ...]onInternal Server Error, turning opaque 500s into actionable text. Gated on 500 so validation, auth, and not-found errors skip the extrapolicies.list()round trip.
quiltx catalog loginopens<registry>/loginin the browser and prompts for a paste-back code on interactive TTYs (works with any auth backend, including SSO).--no-browserfalls back to username/password;--usernameand--api-keypaths are unchanged.
quiltx bucket addon already-registered buckets reapplies S3 bucket policy / SNS / cross-account principals instead of silently skipping.--forcestill removes and re-adds the catalog registration so Quilt re-subscribes SQS.quiltx bucket adderrors print exception type; full traceback underQUILTX_VERBOSE=1.- On opaque
Internal Server Errorfrom policy create / update / delete,quiltx catalog aclwarnings now append the desired permission set and a refetch of server-side state.
quiltx catalog acldedupes(bucket, level)permissions when a bucket appears in bothbuckets.readandbuckets.read_write(RW implies R) — previously tripped the registry's composite PK as an opaque 500 frompolicyCreateManaged.quiltx catalog aclprunes SSO mappings referencing orphaned roles when a managed-policy create fails, so surviving roles still land (previously the wholesetSsoConfigrejected withRolesNotFound, wiping all SSO state). If the prune would dropdefault_role, the SSO update is skipped with a clear warning.quiltx catalog aclno longer emitsadmin: falsefor non-admin SSO mappings — underunion_rolesthe server treatsadminas tri-state andfalsevetoed admin grants from co-matching admin roles.quiltx bucket addno longer performs a direct S3b.ls()access check (stale local creds caused false negatives).is_auth_errormatches only HTTP 401 and the literalUnauthorizedGraphQL payload, stopping false re-auth loops triggered by unrelatedGraphQLClientGraphQLMultiErrorpayloads (e.g. "Bucket not found", validation errors).
This release reshapes quiltx's identity and auth surface around a per-catalog model and switches the stored secret from username/password+refresh-token to a single qk_... API key per DNS. quiltx no longer mutates the user's global quilt3.config() to do its work, no longer consumes quilt3's credentials.json/auth.json, and no longer relies on Quilt-minted AWS session credentials — AWS calls flow through the standard boto3 chain. Scripts that referenced the old quiltx stack ... surface, --catalog-name, or --username/--password will fail at argparse time — there are no aliases (pre-1.0).
- New
quiltx catalognamespace:quiltx catalog default [<dns>] [--clear]— read, set, or clear quiltx's own default catalog (stored inuser_data_path("quiltx")/config.json, never inquilt3.config()). On first run with an empty userconfig, bootstraps the default fromquilt3.config()once. When<dns>has no stored API key, delegates toquiltx catalog loginso first-time set validates that the catalog is reachable.quiltx catalog login --catalog <dns> [--username U --password P | --api-key qk_...] [--key-name N] [--expires-in-days N]— mint a long-livedqk_...API key from username/password (composes/api/login→/api/token→ GraphQLapiKeyCreate) and store it in the system keyring. Surfaces the catalog's own error verbatim on SSO-only catalogs and prompts users to paste a manually-issued key via--api-keyinstead.quiltx catalog list— list catalogs with stored credentials (DNS, username, never the secret).quiltx catalog forget <dns>— delete keyring entry for a DNS. Idempotent. Does not touch the default catalog or stack payload cache.quiltx catalog acl(renamed fromquiltx stack acl).quiltx catalog stack(renamed fromquiltx stack cfn).
- Per-DNS credential storage backed by the system keyring (Keychain / Credential Manager / Secret Service). Storage shape is
{api_key, name?, expires_at?}; legacy{username, secret}entries from earlier development snapshots are ignored on read. Linux without a keyring backend falls back to mode-0600 JSON atuser_data_path("quiltx")/credentials.jsonwith a loud first-run warning. - Per-catalog auth seam:
Catalog.ensure_auth()resolves oneqk_...API key, then under a serialising lock bindsquilt3to that catalog (via a one-timeContextVar-backed monkey-patch onquilt3.session.get_registry_url, noconfig.ymlwrites) and callslogin_with_api_key(). Per-DNS isolation; auth-error retries re-prompt only the catalog that failed viaensure_auth(skip_keyring=True). - Universal CLI flags:
--api-key,--no-prompt,--verbose. Verbose preflight prints a four-linecatalog/source/auth/regionblock to stderr;_probe_auth_source()is read-only (no prompts, no writes). --insecureflag on every command that talks to a catalog. Only accepted when the catalog DNS resolves tolocalhost; any other target is refused. Switches the catalog URL fromhttps://tohttp://localhost. Never persisted — must be passed on every invocation.--catalogand the positionaldnsargument tocatalog defaultaccept either a bare DNS name (open.quiltdata.com) or a fullhttps://URL (https://open.quiltdata.com/); the URL form is normalized to DNS at the input boundary.- Environment variables:
QUILTX_CATALOG,QUILTX_API_KEY,QUILTX_NO_PROMPT,QUILTX_VERBOSE. - Public API for embedding:
from quiltx import Catalog; Catalog.from_dns(dns, source="flag", api_key=...). Constructor does no I/O; admin/AWS access is lazy. quiltx catalog listrendersDNS / KEY NAME / VALID UNTIL / STATUScolumns. Status is derived from localexpires_atonly (no network probe):ACTIVE/EXPIRES SOON(<14 days) /EXPIRED/UNKNOWN.Catalog.aws_session(profile=...)returns a plainboto3.Sessionfrom the standard AWS SDK chain — noquilt3import, no Quilt-minted credentials.cfn_client()andbucket._lightweight_stack_payload()likewise use ambient AWS chain and surface a clear error if no AWS creds are available.quiltx bucket add --no-promptrequires--yes(or--dry-run); profile-fallback prompts are also suppressed in headless mode.
--catalog-nameis renamed--catalogeverywhere it appeared.logs,ecs shell,ecs run-migration, andcatalog stack(bootstrap) now flow through the unified@catalog_command(auth=False)resolver.quilt3access is consolidated behindquiltx.quilt3_facade; runtime callers no longer importquilt3directly.
quiltx stacknamespace and all its subcommands (replaced byquiltx catalog).quiltx stack catalog(the URL-setter that wrote toquilt3.config()— global-state mutation no longer fits the multi-catalog model).quiltx.config.set_catalog_urlandget_catalog_url(zero callers post-multi-auth).--username/--passwordflags andQUILTX_USERNAME/QUILTX_PASSWORDenv vars (replaced by--api-key/QUILTX_API_KEY).quiltx/quilt_auth.py(acquire_refresh_token,validate_refresh_token),quilt3_facade.login_with_token, andquilt3_facade.default_boto3_session— quiltx no longer mints refresh tokens or consumes Quilt-rotated AWS session credentials. AWS calls go through the standard SDK chain.Catalog.boto3_session()(replaced byCatalog.aws_session(profile=...)).
- Catalog identifier normalization rejects
http://, custom ports, and IP literals; previously these passed silently throughget_hostname.
- Union-of-matches SSO role assignment:
quiltx stack aclnow always emitsunion_roles: truein the generated SSO config, so a user matching multiple mappings gets all of those roles (requires a registry that consumes the flag). quiltx bucket removeunregisters a bucket from the Quilt catalog (leaves S3 policy / SNS / notifications intact).quiltx bucket add --forcere-applies the S3 bucket policy, SNS topic policy, and notification config when the bucket is already registered, and performs a remove-then-add against the catalog so Quilt re-subscribes its SQS queues to the bucket's SNS topic.
- Renamed the canonical ACL example to
stack-acl.example.yamlat the repo root.
quiltx stack aclpolicy updates no longer silently fail: resolve the policy id from current state before callingadmin_policies.update_managed(the title-based fallback was unreachable becausequilt3raised 500 on non-UUID inputs), and preserve existing role attachments in the update.quiltx bucketverification prints a prominent FAILED line identifying the failing stage, probes the catalog search index to confirm SNS→SQS wiring actually landed, and no longer trips AccessDenied on bucket-metadata calls (GetBucketLocation,GetBucketVersioning,GetBucketNotification,GetBucketCORS,GetBucketTaggingadded toQUILT_POLICY_ACTIONS).
- Publish workflow now serializes concurrent runs on
mainvia apublishconcurrency group, and tolerates a pre-existing tag gracefully (skips GitHub release + PyPI publish steps rather than failing afteruv build).
- Auto-release on merge to
mainwhenpyproject.tomlversion is bumped. The publish workflow now triggers on push tomain, tagsv$VERSIONif the tag is new, and publishes to PyPI. No more manual./poe tagstep. If the version tag already exists, the run is a no-op.
quiltx bucket add --principal ARNflag to set the IAM principal(s) granted cross-account access in the bucket policy. Repeatable or comma-separated. Bare--principalprints guidance on choosing Quilt service role ARNs.
quiltx bucket add --stack-onlyflag. It restricted the bucket policy to the stack'sRegistryRoleARN, which is the ECS task execution role — not a role Quilt uses to access data buckets. Quilt does not publish an official list of roles for the bucket policy; the documented principal is the control account root. Use--principal ARNif you want to narrow access yourself.
quiltx bucket addno longer requires CloudFormation access in any account: when the Quilt stack role lackscloudformation:DescribeStacks, it derivesaccount_idfromsts:GetCallerIdentityon the Quilt session and readsregionfrom the catalogconfig.json.
quiltx bucket add --stack-onlyflag to restrict the bucket policy principal to the stack's RegistryRoleARN instead of the entire control account- Direct-ACL specification (
spec/060-stack-acl/08-direct-acl.md) and example YAML files (dynamic-roles.yaml,static-policies.yaml) quiltx stack catalog --ca-bundle PATHand--insecureflags for catalogs behind corporate TLS-inspection proxies or with self-signed certificates
- BREAKING:
quiltx stack aclnow only accepts the flatpolicies:/roles:format; the oldbucket_policies:/roles:/sso:schema is rejected quiltx stack aclnow synthesizes cumulative managed roles from policy order, generates inline managed policies for static-role bucket grants, and derives SSO mappings directly from policy and role audiencesquiltx stack aclno longer prompts for a default role;config.default_role: trueon a policy controls the emitted SSO default role- Stack ACL docs now use
spec/060-stack-acl/simpler-stack-acl.ymlas the canonical example and explain the order-sensitive synthetic role model - CloudFormation discovery now uses
quilt3.session.get_boto3_session()when available, soquiltx bucketand stack discovery work for users who have runquilt3 loginwithout needing CFN permissions on their own AWS identity quiltx bucketcommands are wrapped with@auto_login, re-prompting forquilt3 loginon auth errors
- Reject ACL config names that would collide with reserved generated inline-policy titles ending in
__inline - Delete stale synthesized roles in the same reconciliation pass after policy rename/reorder by deriving role deletions from the desired role set instead of the current SSO snapshot
- Confirmation prompt for
quiltx ecs run-migrationshowing stack, cluster, and task definition before execution; skip with--yes
quiltx ecs run-migrationto re-run the registry migration ECS task for a stack using cached CloudFormation metadata- Public
quiltx.ecshelpers for finding the migration task definition, resolving registry service networking, launching the task, and waiting for completion - Explicit ECS launch-failure reporting for migration reruns, including surfaced
run_task()failure reasons - Lake Formation troubleshooting docs for the stack ACL rollout, including the post-mortem, migration rerun spec, status tabulation, and a datasets ACL example
- BREAKING:
quiltx ecsis now a subcommand namespace; usequiltx ecs shellfor interactive task access instead of barequiltx ecs - README now documents the split ECS CLI (
ecs shell,ecs run-migration) and thequiltx.ecsPython API
quiltx stack aclnow always shows each apply step (-> add bucket,-> create policy, etc.) regardless of--verbose, so users can see which operation failed- GraphQL error details (path, message, locations) are always shown on failure, not just in
--verbosemode - Bucket and policy creation failures are caught and reported immediately with context (e.g. which failed buckets a policy references), then apply continues with remaining operations
- Role creation, SSO config, and delete failures are similarly caught and reported without aborting
quiltx stack acl <config.yml>for declarative reconciliation of Quilt buckets, managed policies, managed roles, and SSO mappings from YAMLquiltx stack acl(no args) dumps the current server ACL state for inspection--dry-runflag to preview ACL changes without applying them--verboseflag for detailed diff output including SSO and default-role details- Progress output during ACL apply (bucket, policy, role, SSO steps)
- SSO create-vs-update detection: creates new SSO config or updates existing one as needed
- Default role configuration moved into SSO config for cleaner YAML semantics
auto_logindecorator inquiltx.configfor automatic session refresh on auth failurenormalize_catalog_url()helper inquiltx.config- Public Python API:
AclConfig,AclDiff,CurrentState,all_buckets,apply_acl,build_sso_config,compute_diff,fetch_current_state,parse_acl_config,print_diffexported fromquiltx
- Add
pyyamlas a runtime dependency for YAML-backed ACL configuration - Require
quilt3>=7.3.0soquiltx stack aclcan use the new admin policies API set_catalog_url()now normalizes the URL (addshttps://, strips trailing slash)
- BREAKING:
quiltx stackis now a subcommand namespace with:quiltx stack catalog— show/set the Quilt catalog (replacesquiltx config)quiltx stack cfn— discover the CloudFormation stack (replaces barequiltx stack)
- BREAKING:
quiltx configremoved as a top-level command; usequiltx stack cataloginstead bucket addauto-discovers CloudFormation stack when no cached metadata exists, removing the need to runquiltx stack cfnfirst
- Remove
s3:GetBucketNotificationands3:PutBucketNotificationfrom cross-account bucket policy (#20)
- Fix publish workflow: remove
gh release createfrompoe tagto avoid conflict with CI release step
- Configure Renovate for grouped major/minor+patch dependency PRs, disable Dependabot
- Hyperlink "available" to PyPI release page in release notes script
poe tagrelease notes now embed actual CHANGELOG content instead of GitHub-generated PR linkspoe tagusesscripts/release_notes.pyto extract notes from CHANGELOG.md- README: use
uvx quiltxconsistently throughout, drop "Install" section
buckettool for registering cross-account S3 buckets with Quilt:quiltx bucket add|list|test- merge/update S3 bucket policy and bucket notifications
- create or reuse SNS topics and patch topic policies for S3 publish plus Quilt
RegistryRoleARNsubscribe access bucket addautomatically runs the same registration/read verification asbucket testunless--no-testis setbucket testverifies the bucket is registered in Quilt and readable from the control account--profile,--dry-run,--title, and--no-testsupport for data-account workflows- Rich context tables and JSON syntax highlighting for dry-run/confirmation output
- Documentation and Read the Docs integration:
- MkDocs documentation site with Material theme
- Read the Docs configuration for automated docs building
- Comprehensive API reference documentation with mkdocstrings
- User guides for CLI tools and Stack API
- Getting started guide and contributing documentation
- Dark mode support and enhanced navigation
- New semantic configuration functions:
get_catalog_config(): Get the full quilt3 catalog configurationget_catalog_url(): Get the catalog URL from configurationget_catalog_region(): Get the AWS region from configurationset_catalog_url(): Set the catalog URL in quilt3 configuration
- BREAKING: Removed
configured_catalog()function- Replace
configured_catalog()withget_catalog_config()for full config - Replace
configured_catalog()["navigator_url"]withget_catalog_url() - Use
set_catalog_url()to configure a new catalog instead ofconfigured_catalog(url)
- Replace
- All new functions have clear, semantic names that indicate whether they read or write
- New functions raise
ValueErrorwith helpful messages when catalog is not configured - Documentation improvements:
- README simplified with focus on installation and quick examples
- AGENTS.md streamlined for developer reference
- API reference updated to use new config function names
- Contributing guide updated with new API exports
- Documentation now properly references the new config API instead of deprecated
configured_catalog()
- Version bump to 0.2.1 for intermediate release
- New
ecstool: Interactive shell access to ECS tasks- Open interactive shells in running ECS containers using AWS Session Manager
- Automatic Session Manager plugin detection with installation instructions
- Smart defaults: Auto-selects RegistryService and remembers previous selections
- Reachability checks: Test network connectivity to catalog services from ECS (
--reachability) - Execute Command management: Automatically detects and enables Execute Command on services
- Interactive prompts for cluster/service selection with
--promptflag - List mode: View available ECS clusters and services with
--list - Region auto-detection from stack payload
- New
utilsmodule: General utility functionsget_bucket_region(): Get AWS region of S3 bucketsnormalize_url(): Normalize URLs to canonical formget_hostname(): Extract hostname from URLs
- Stack payload enhancements:
- ECS resources now included in stack payload (
ecs_resources) - Catalog configuration cached in stack payload (
catalog_config) - Version tracking with
quiltx_versionfield - New
load_stack_payload()function for loading cached data - New
ensure_min_version()function for version compatibility checks
- ECS resources now included in stack payload (
- Stack API improvements:
- New
list_ecs_resources()function for discovering ECS clusters/services - Auto-detection of AWS region from catalog configuration
- Automatic boto3 client creation when not provided
- New
- Stack API simplified: CloudFormation client now optional
find_matching_stack(): Now acceptsregionparameter and creates client automaticallylist_log_group_resources(): Now acceptsregionparameter and creates client automatically- All stack functions can optionally accept pre-configured boto3 clients for advanced use cases
- Code organization:
- Moved
configured_catalog()to separatequiltx.configmodule - Created
quiltx._versionmodule for centralized version management - Reduced exports from
quiltx.__init__to only__version__andconfigured_catalog
- Moved
- Developer tooling:
- Updated
bump_version.pyscript to use_version.pyinstead of__init__.py
- Updated
- Publishing workflow improvements:
- Automated PyPI publishing now triggers directly on git tag pushes (no manual GitHub Release creation needed)
- GitHub Releases are automatically created with release notes when tags are pushed
- Build system switched from pip to uv for faster, more reliable builds
- Distribution files (wheel and tarball) automatically attached to GitHub Releases
logstool: Enhanced log display and filtering capabilities- Stream-based filtering: Filter logs by stream name with substring matching (e.g.,
quiltx ecs logs registry/registry) --wrapflag: Option to wrap long log messages instead of truncating (auto-enabled when filtering by stream)- Health check coalescing: Consecutive health check log entries are automatically summarized to reduce noise
- Default behavior now shows all log streams instead of just LogGroup
- Stream-based filtering: Filter logs by stream name with substring matching (e.g.,
- Developer tooling improvements:
- Enhanced
bump_version.pyscript with automated git commit workflow - Version bumping now automatically updates
uv.lockand commits all changes - Added git status validation to prevent bumping with uncommitted changes
- Enhanced
logstool positional arguments now filter by stream name instead of log group keys- Health check detection improved to recognize ELB health checker and GET / requests
stacktool: Discover and cache CloudFormation stack metadata with catalog matching--catalog-nameflag for flexible catalog specification without quilt3 config- Summary display showing stack name, region, account, and resource counts
logstool: Retrieve and follow CloudWatch logs with dynamic display- Follow mode enabled by default with single-screen dynamic updates using Rich Live
- Time-based filtering (--since, --until)
- Color-coded log levels (ERROR=red, WARN=yellow, INFO=blue, DEBUG=dim)
- Auto-detecting console size and stream management
- CLI improvements: Subparsers showing all available tools with descriptions
- Developer tooling enhancements:
- Pre-commit hooks with Black and mypy
- CI lint validation workflow
- Poe task sequences for automated dependency management (
./poe setup,./poe sync) - Simplified developer documentation in AGENTS.md
Initial release of quiltx - a unified toolkit for Quilt workflows.
- Unified CLI with single
quiltxentry point - Built-in tool:
configfor configuring Quilt catalogs usingconfigured_catalogAPI - Automatic tool discovery system (no explicit registry needed)
- Shared utilities library with
configured_cataloghelper - Comprehensive tests for CLI and config tool