Repository navigation
feat(projects): enforce Project membership and retire the connector #8590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
+36,936
−1,786
Draft
Changes from all commits
Commits
Show all changes
134 commits
Select commit
Hold shift + click to select a range
00a83d0
feat(projects): add project identity and lifecycle foundation
mzxchandra aa9b415
feat(projects): create projects with their initial environment
mzxchandra 91cba23
docs(projects): record project files follow-up
mzxchandra 0980ad1
docs(projects): explain project and workspace creation flows
mzxchandra a14b448
fix(projects): stage activation after compatible writers deploy
mzxchandra 5121347
feat(projects): enforce membership after the staged backfill
mzxchandra 523338a
fix(projects): retry writes after concurrent membership changes
mzxchandra dc5e301
fix(projects): align integration fixtures with membership constraints
mzxchandra c1c8e5d
refactor(projects): prepare compatible writers for the SQL backfill
mzxchandra 2e94a13
Merge branch 'feat/project-entity-foundation' into codex/project-enti…
mzxchandra 5e11d7d
refactor(projects): backfill through bounded SQL migration batches
mzxchandra 99189f2
fix(projects): clean up automatically created fixture Projects
mzxchandra 78f773d
Merge branch 'feat/project-entity-foundation' into codex/project-enti…
mzxchandra 2ecbfdf
fix(projects): backfill only families missing membership
mzxchandra 30bc9d8
chore(projects): merge staging into foundation
mzxchandra b5cc3c4
chore(projects): merge updated foundation into enforcement
mzxchandra 2afc652
fix(projects): bound the trigger installation lock window
mzxchandra 6dfbc4f
fix(workflows): guard restore against concurrent workspace archive
mzxchandra 8965210
fix(projects): keep workflow lifecycle guards at workspace scope
mzxchandra 552ce68
fix(workflows): guard restore against concurrent workspace archive
mzxchandra 8be18e5
Merge branch 'feat/project-entity-foundation' into codex/project-enti…
mzxchandra 0b7eed6
fix(projects): close lifecycle races and surface rollout conflicts
mzxchandra b8c44e9
Merge branch 'feat/project-entity-foundation' into codex/project-enti…
mzxchandra 634b19e
fix(workflows): return not found when import loses archive race
mzxchandra 40ea011
Merge branch 'feat/project-entity-foundation' into codex/project-enti…
mzxchandra fd874d0
fix(projects): tighten rollout checks and deduplicate lifecycle valid…
mzxchandra d3c56a0
test(projects): detect missing lifecycle validation calls
mzxchandra 8f36f2d
test(projects): verify concurrent lifecycle lock contention
mzxchandra 7ec83f0
chore(projects): merge staging into membership enforcement
mzxchandra ef5498a
test(projects): update new workspace fixtures for enforcement
mzxchandra 41b3a28
chore(projects): sync enforcement migrations with staging
mzxchandra 10a5f06
chore(projects): follow staging table migration
mzxchandra 28b0017
chore(projects): merge staging and advance enforcement migration
mzxchandra e2b8dfa
fix(tests): create Project membership in desktop and CLI fixtures
mzxchandra 3cf5483
Merge staging into project enforcement and advance migration to 0402
mzxchandra 947fda1
Merge pinned staging and advance Project enforcement to 0403
mzxchandra ab1e8cb
Merge pinned staging table ordering changes and provision dispatcher …
mzxchandra d4635ed
Merge pinned staging acquisition attribution changes
mzxchandra 83bdee2
fix(tests): restore Project enforcement fixtures after migration renu…
mzxchandra 61ffede
fix(tests): scope migration probes and align remaining Project fixtures
mzxchandra 5e8380d
feat(projects): prepare workspace project column compatibility
mzxchandra 235d1e2
test(projects): clean up compatibility fixtures atomically
mzxchandra 4297631
refactor(projects): enforce membership through workspace project column
mzxchandra f781687
merge compatibility fixture validation into column enforcement
mzxchandra e32fda6
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 363a0e1
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 202c28e
feat(projects): move membership to workspace column with rollout bridge
mzxchandra 744dd0d
Merge column-only Project membership and retire connector after rollout
mzxchandra 9a29636
Merge staging and order Project column expansion after workflow tests
mzxchandra 51ff1dc
Merge staging and order Project enforcement after column expansion
mzxchandra d6b7a5d
test(projects): align transfer mocks with workspace membership
mzxchandra d782078
Merge Project transfer fixture corrections into enforcement
mzxchandra 1376167
test(projects): provision required membership in transfer unit fixtures
mzxchandra 031ec26
improvement(workspaces): present API responses explicitly
mzxchandra 0933be0
Merge workspace response projection from Project column expansion
mzxchandra 3e4c88c
feat(projects): prepare legacy membership with a resumable operator tool
mzxchandra 49e32c7
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra c375ebc
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 4a4b85e
fix(projects): support PostgreSQL 16 column migration
mzxchandra 243af21
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra a8c36a1
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 786ac33
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 1ce07fa
fix(projects): allow multi-batch copies to finish
mzxchandra c240b7f
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 39f54a0
fix(projects): support PostgreSQL 16 preparation and current fixtures
mzxchandra 8423fec
fix(projects): reconcile memberships during schema push
mzxchandra 6d4185b
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra a9c33fe
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 8f06830
fix(projects): enforce safe schema push provisioning
mzxchandra 677186f
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra c2b95cb
test(projects): provision newly merged workspace fixtures
mzxchandra 2762a31
fix(projects): use the direct connection for push reconciliation
mzxchandra 50361dc
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 1d88662
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra d1c7457
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra abc8ac6
test(billing): wait for parked transactions before racing writers
mzxchandra 97a439e
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra e73ed2d
test(billing): freeze the clock for exact deadline assertions
mzxchandra 7f8eb18
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra b653f5e
fix(projects): close operator verification and contention gaps
mzxchandra 38d192d
test(billing): stabilize member ledger timeout checks
mzxchandra 8c3c334
fix(projects): await cleanup and bound backfill artifacts
mzxchandra 454e2e2
fix(projects): honor operator cancellation and status exits
mzxchandra fb27e1b
fix(projects): reject verification of conflicted plans
mzxchandra 88d10da
fix(projects): defer archive repair on database contention
mzxchandra 4025e5a
fix(projects): coordinate read-only maintenance commands
mzxchandra ce760cc
ci(projects): use the standard PostgreSQL test coverage
mzxchandra 8323bd3
fix(projects): support trigger-free column rollout
mzxchandra c5ff743
fix(projects): run bounded membership backfill before enforcement
mzxchandra 72da20a
Merge trigger-free expansion into project enforcement
mzxchandra 7613c14
test(projects): verify column-only archive repair assignment
mzxchandra f0ce089
fix(projects): retain healthy indexes during schema push
mzxchandra 8e35470
Merge schema-push index fix into project enforcement
mzxchandra e92ba0b
ci(projects): use standard integration coverage for enforcement
mzxchandra bcc1011
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 0dfc7ab
fix(projects): correct rollout fixtures and schema-push index
mzxchandra bdf50b2
fix(projects): reconcile assigned environments before enforcement
mzxchandra ecfdf8b
chore(projects): integrate validated column expansion into enforcement
mzxchandra d9743bb
fix(projects): preserve backfill repair and resume guarantees
mzxchandra 639c8ca
test(projects): align fixture lifecycle with enforced project ownership
mzxchandra 1e4499e
fix(projects): integrate reviewed repair and fixture corrections
mzxchandra b7ff6b1
Merge staging and renumber Project expansion migration to 0405
mzxchandra c704293
test(projects): skip archive repair suite when Redis is unset
mzxchandra b2718cb
merge: integrate renumbered Project expansion and staging fixtures
mzxchandra d0a9792
chore(projects): normalize enforcement SQL whitespace
mzxchandra d8a9627
feat(projects): commit membership authority before reconciliation
mzxchandra ceb7cf3
fix(projects): switch membership authority after compatible rollout
mzxchandra b9bc572
Merge staging and advance Project expansion migration to 0406
mzxchandra 32f49e3
merge: integrate Project authority switch into enforcement
mzxchandra 406a78f
merge: sync Project enforcement with expansion 0406
mzxchandra 8a3993f
test(projects): guard optional authority fixtures explicitly
mzxchandra e5da5c8
merge: synchronize expansion fixture lint fix
mzxchandra 9edfcde
test(projects): seed authority in billing lock-order mock
mzxchandra d1443c8
merge: synchronize expansion billing fixture fix
mzxchandra 9856595
fix(projects): bound authority barriers and verify push replay
mzxchandra 14554d0
Merge bounded authority barrier and replay review fixes
mzxchandra 357740a
fix(projects): pin operator schema and pace detach repairs
mzxchandra 5cd7ada
docs(projects): record native constraint rollout decisions
mzxchandra 69df502
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 36b0074
refactor(projects): replace integrity triggers with native foreign keys
mzxchandra 1988c88
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 467d269
fix(projects): recognize completed rollout without its marker
mzxchandra d4e3da6
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra d2f0893
fix(projects): retire rollout marker with legacy membership
mzxchandra 5dc6f90
test(projects): model expansion authority in workspace move fixtures
mzxchandra 0a199ba
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 204e5f1
fix(projects): keep repair reads compatible with expansion schema
mzxchandra 88977f3
fix(projects): retain project name for workspace archival
mzxchandra 744885c
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra f73e737
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 930cb76
docs(projects): consolidate permanent storage rules in README
mzxchandra 34798aa
Merge remote-tracking branch 'origin/staging' into feat/project-works…
mzxchandra 1b2795d
Merge branch 'feat/project-workspace-column-expand' into codex/projec…
mzxchandra 5351d14
Merge staging after Project expansion squash
mzxchandra File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| #!/usr/bin/env python3 | ||
| """Read-only, fail-closed ECS retirement check for the Project column contract migration. | ||
|
|
||
| The expected digest acknowledges fully deployed #8830 transaction-barrier and durable-authority support | ||
| and retirement of every incompatible server and relevant old worker job before switching. Every live and supported | ||
| rollback application must tolerate project_workspace being absent. | ||
| AWS checks below independently verify ECS retirement, not worker drainage. | ||
| """ | ||
| import argparse | ||
| import datetime | ||
| import json | ||
| import re | ||
| import subprocess | ||
| import sys | ||
|
|
||
|
|
||
| def aws(region, *args): | ||
| result = subprocess.run( | ||
| ['aws', '--region', region, '--no-cli-pager', '--cli-connect-timeout', '10', '--cli-read-timeout', '30', *args, '--output', 'json'], | ||
| capture_output=True, text=True, timeout=90, check=False, | ||
| ) | ||
| if result.returncode: | ||
| raise RuntimeError('AWS preflight read failed; check deployment-read permissions') | ||
| return json.loads(result.stdout) | ||
|
|
||
|
|
||
| def latest_execution(region, pipeline): | ||
| executions = aws(region, 'codepipeline', 'list-pipeline-executions', '--pipeline-name', pipeline).get('pipelineExecutionSummaries', []) | ||
| def epoch(execution): | ||
| value = execution['startTime'] | ||
| return value if isinstance(value, (int, float)) else datetime.datetime.fromisoformat(value.replace('Z', '+00:00')).timestamp() | ||
| if not executions: | ||
| raise RuntimeError('No application deployment execution was found') | ||
| return max(executions, key=epoch) | ||
|
|
||
|
|
||
| def matches_release(execution, digest): | ||
| return execution.get('status') == 'Succeeded' and any( | ||
| revision.get('actionName') == 'ECR_Source' and revision.get('revisionId') == digest | ||
| for revision in execution.get('sourceRevisions', []) | ||
| ) | ||
|
|
||
|
|
||
| def verify(environment, region, digest): | ||
| if not re.fullmatch(r'sha256:[0-9a-f]{64}', digest): | ||
| raise RuntimeError('Set the environment-specific PROJECT_COLUMN_ENFORCEMENT_READY_IMAGE_DIGEST after verifying #8830 authority-aware readers/writers, transaction barriers and all incompatible server/worker drainage') | ||
| pipeline = f'sim-{environment}-{region}-app-deployment' | ||
| execution = latest_execution(region, pipeline) | ||
| if not matches_release(execution, digest): | ||
| raise RuntimeError('The latest app pipeline has not completed for the acknowledged image; traffic cutover alone is insufficient') | ||
| execution_id = execution['pipelineExecutionId'] | ||
| group = aws(region, 'deploy', 'get-deployment-group', '--application-name', f'sim-{environment}-{region}-ecs-app', | ||
| '--deployment-group-name', f'sim-{environment}-{region}-app-dg')['deploymentGroupInfo'] | ||
| services = group.get('ecsServices', []) | ||
| if len(services) != 1: | ||
| raise RuntimeError('Expected exactly one application ECS service') | ||
| cluster, service = services[0]['clusterName'], services[0]['serviceName'] | ||
| description = aws(region, 'ecs', 'describe-services', '--cluster', cluster, '--services', service) | ||
| if description.get('failures') or len(description.get('services', [])) != 1: | ||
| raise RuntimeError('Cannot inspect the application ECS service') | ||
| record = description['services'][0] | ||
| if record.get('desiredCount', 0) < 1 or record.get('runningCount') != record['desiredCount'] or record.get('pendingCount') != 0: | ||
| raise RuntimeError('Application ECS service is not stable') | ||
| arns = set() | ||
| for status in ('RUNNING', 'STOPPED'): | ||
| arns.update(aws(region, 'ecs', 'list-tasks', '--cluster', cluster, '--service-name', service, | ||
| '--desired-status', status).get('taskArns', [])) | ||
| live = [] | ||
| ordered = sorted(arns) | ||
| for start in range(0, len(ordered), 100): | ||
| response = aws(region, 'ecs', 'describe-tasks', '--cluster', cluster, '--tasks', *ordered[start:start + 100]) | ||
| if response.get('failures'): | ||
| raise RuntimeError('Cannot account for every ECS task') | ||
| if len(response.get('tasks', [])) != len(ordered[start:start + 100]): | ||
| raise RuntimeError('Incomplete ECS task response') | ||
| live.extend(task for task in response['tasks'] if task.get('lastStatus') != 'STOPPED') | ||
| if len(live) != record['desiredCount']: | ||
| raise RuntimeError('Old, stopping, or pending ECS tasks remain') | ||
| for task in live: | ||
| app = [container for container in task.get('containers', []) if container.get('name') == 'app'] | ||
| if task.get('lastStatus') != 'RUNNING' or task.get('desiredStatus') != 'RUNNING' or len(app) != 1 or app[0].get('imageDigest') != digest: | ||
| raise RuntimeError('A live ECS task does not match the acknowledged compatible release') | ||
| latest = latest_execution(region, pipeline) | ||
| if latest.get('pipelineExecutionId') != execution_id or not matches_release(latest, digest): | ||
|
mzxchandra marked this conversation as resolved.
|
||
| raise RuntimeError('Application deployment changed during preflight') | ||
| print(json.dumps({'ecsRetired': True, 'expectedImageDigest': digest, 'pipelineExecutionId': execution_id, | ||
| 'operatorAcknowledgedColumnWritersAndWorkers': True})) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument('--environment', required=True, choices=['production', 'staging']) | ||
| parser.add_argument('--region', required=True) | ||
| parser.add_argument('--expected-image-digest', required=True) | ||
| args = parser.parse_args() | ||
| try: | ||
| verify(args.environment, args.region, args.expected_image_digest) | ||
| except (RuntimeError, ValueError, KeyError, TypeError, subprocess.TimeoutExpired) as error: | ||
| print(f'Project column rollout preflight refused: {error}', file=sys.stderr) | ||
| sys.exit(1) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.