AWS host phase 3: connect Triple-C to an AWS account and check what it's allowed to do there. Spec: docs/superpowers/specs/2026-11-13-aws-ecs-host-design.md; plan: docs/superpowers/plans/2026-11-14-aws-connection-permission-check.md.
Nothing here starts AWS resources, and it ships no release by itself.
What users get
Settings → Hosts: "Local Docker" plus AWS connections. A connection is an AWS profile (SSO included) or access keys, plus a default region.
Keys live in the OS keychain, never settings.json.
Saving shows "Signed in as <arn>". An expired or revoked SSO session offers Sign in.
Check: reports Environment admin, Workspace user or Insufficient and names each missing action, with buttons to copy the policies for an admin.
It runs iam:SimulatePrincipalPolicy as the caller.
If simulation isn't permitted, it falls back to read-only probes, marks write actions unverified, and never reports more than "Workspace user (unverified)".
Throttled or failed checks show "Incomplete — check again", never a false Insufficient.
Settings export/import: carries connections and keys. The import preview discloses added, replaced (naming your local connection), removed and unverifiable entries.
Shipped IAM policies (aws/)
workspace-user.json, environment-admin.json and permissions-boundary.json, plus aws/README.md covering isolation guarantees, invariants, known gaps for phases 4–6, and the live-verification table.
Users can't reach each other's workspaces. Stop, exec, session, PassRole, secrets and access points are all scoped by the triple-c:owner tag. Users can never set triple-c:component, and environment secrets can't be claimed. User secrets must use the environment KMS key, and an explicit Deny blocks every other key.
Environment admins are bounded.
They can only create triple-c-* roles that carry the permissions boundary, and they can't remove, replace or edit that boundary.
Their destructive actions are tag-scoped.
Deploying stacks with a CloudFormation service role is denied.
A drift test keeps the Rust check table and the JSON policies identical. An in-repo evaluator checks the isolation rules, including both tiers attached together. Further tests enforce ARN-or-* resources and the managed-policy size limit.
Verified against a real account
cargo test aws::live_tests -- --ignored --test-threads=1 with TRIPLEC_AWS_E2E_PROFILE / TRIPLEC_AWS_E2E_REGION. It passes 10/10 using throwaway triple-c-e2e-* roles and as an SSO admin session.
Real IAM disagreed with the policies in five places, all fixed:
${aws:PrincipalArn} is rejected as a Resource, so neither policy could even be attached.
ECS Exec also authorizes against the cluster.
Secrets Manager needs kms:Decrypt.
EFS CreateFileSystem needs *.
ssmmessages:OpenDataChannel is needed. This one was added from AWS documentation, not a live denial.
Items needing real ECS/EFS/EC2 resources are listed in the README for phases 4–6. All test resources were cleaned up; spend was under $0.05.
Notable changes outside the new modules
SettingsStore::update now saves before replacing the in-memory copy, so a failed save no longer leaves memory and disk diverged. A new modify does a read-modify-save under the lock.
update_settings keeps hosts as stored, the same as marketplace fields; import re-applies imported hosts.
run_sso_login passes --profile=<name> as a single argv element.
New crates: aws-sdk-sts, -iam, -cloudformation and -secretsmanager, plus aws-sdk-kms as a dev-dependency. They are default-features = false, and the legacy rustls 0.21 stack is still absent.
Design rulings made during implementation (recorded in the spec)
Permissions-boundary model for environment admins. The one-time creation of triple-c-permissions-boundary is a phase-4 design item.
Strict tenancy needs per-user execution roles too (phase 4).
The environment admin is a trusted operator of its environment.
Principal inspection is limited to SSO permission-set roles and triple-c-* roles. Users signing in through other roles fall back to probes; the README explains how an admin can add them.
China and GovCloud regions are rejected until the policies handle other partitions.
For phase 4
workspace-user.json is about 30 characters under the 6,144-character managed-policy limit, so it must be split.
Nothing sensitive may go in task-definition env vars or RunTask overrides, because they are readable via ecs:Describe*.
Testing
cargo test: 1049 passed. vitest: 1194 passed. tsc clean, and the build adds no new warnings. Each task was built by a subagent and reviewed for spec and quality, followed by a whole-branch review, and every finding was fixed.
AWS host **phase 3**: connect Triple-C to an AWS account and check what it's allowed to do there. Spec: `docs/superpowers/specs/2026-11-13-aws-ecs-host-design.md`; plan: `docs/superpowers/plans/2026-11-14-aws-connection-permission-check.md`.
Nothing here starts AWS resources, and it ships no release by itself.
## What users get
- **Settings → Hosts:** "Local Docker" plus AWS connections. A connection is an AWS profile (SSO included) or access keys, plus a default region.
- Keys live in the OS keychain, never `settings.json`.
- Saving shows "Signed in as `<arn>`". An expired or revoked SSO session offers **Sign in**.
- **Check:** reports **Environment admin**, **Workspace user** or **Insufficient** and names each missing action, with buttons to copy the policies for an admin.
- It runs `iam:SimulatePrincipalPolicy` as the caller.
- If simulation isn't permitted, it falls back to read-only probes, marks write actions unverified, and never reports more than "Workspace user (unverified)".
- Throttled or failed checks show "Incomplete — check again", never a false Insufficient.
- **Settings export/import:** carries connections and keys. The import preview discloses added, replaced (naming your local connection), removed and unverifiable entries.
## Shipped IAM policies (`aws/`)
- `workspace-user.json`, `environment-admin.json` and `permissions-boundary.json`, plus `aws/README.md` covering isolation guarantees, invariants, known gaps for phases 4–6, and the live-verification table.
- **Users can't reach each other's workspaces.** Stop, exec, session, PassRole, secrets and access points are all scoped by the `triple-c:owner` tag. Users can never set `triple-c:component`, and environment secrets can't be claimed. User secrets must use the environment KMS key, and an explicit Deny blocks every other key.
- **Environment admins are bounded.**
- They can only create `triple-c-*` roles that carry the permissions boundary, and they can't remove, replace or edit that boundary.
- Their destructive actions are tag-scoped.
- Deploying stacks with a CloudFormation service role is denied.
- **A drift test keeps the Rust check table and the JSON policies identical.** An in-repo evaluator checks the isolation rules, including both tiers attached together. Further tests enforce ARN-or-`*` resources and the managed-policy size limit.
## Verified against a real account
`cargo test aws::live_tests -- --ignored --test-threads=1` with `TRIPLEC_AWS_E2E_PROFILE` / `TRIPLEC_AWS_E2E_REGION`. It passes 10/10 using throwaway `triple-c-e2e-*` roles and as an SSO admin session.
Real IAM disagreed with the policies in five places, all fixed:
- `${aws:PrincipalArn}` is rejected as a Resource, so neither policy could even be attached.
- ECS Exec also authorizes against the cluster.
- Secrets Manager needs `kms:Decrypt`.
- EFS `CreateFileSystem` needs `*`.
- `ssmmessages:OpenDataChannel` is needed. This one was added from AWS documentation, not a live denial.
Items needing real ECS/EFS/EC2 resources are listed in the README for phases 4–6. All test resources were cleaned up; spend was under $0.05.
## Notable changes outside the new modules
- `SettingsStore::update` now saves before replacing the in-memory copy, so a failed save no longer leaves memory and disk diverged. A new `modify` does a read-modify-save under the lock.
- `update_settings` keeps `hosts` as stored, the same as marketplace fields; import re-applies imported hosts.
- `run_sso_login` passes `--profile=<name>` as a single argv element.
- New crates: `aws-sdk-sts`, `-iam`, `-cloudformation` and `-secretsmanager`, plus `aws-sdk-kms` as a dev-dependency. They are `default-features = false`, and the legacy rustls 0.21 stack is still absent.
## Design rulings made during implementation (recorded in the spec)
- Permissions-boundary model for environment admins. The one-time creation of `triple-c-permissions-boundary` is a phase-4 design item.
- Strict tenancy needs per-user execution roles too (phase 4).
- The environment admin is a trusted operator of its environment.
- Principal inspection is limited to SSO permission-set roles and `triple-c-*` roles. Users signing in through other roles fall back to probes; the README explains how an admin can add them.
- China and GovCloud regions are rejected until the policies handle other partitions.
## For phase 4
- `workspace-user.json` is about 30 characters under the 6,144-character managed-policy limit, so it must be split.
- Nothing sensitive may go in task-definition env vars or RunTask overrides, because they are readable via `ecs:Describe*`.
## Testing
`cargo test`: 1049 passed. `vitest`: 1194 passed. `tsc` clean, and the build adds no new warnings. Each task was built by a subagent and reviewed for spec and quality, followed by a whole-branch review, and every finding was fixed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
aws/policies/{workspace-user,environment-admin}.json are the IAM policies
for the two tiers; aws::policies embeds them and holds one representative
simulator check per action. Tests keep table and JSON in lock-step and run
each check through a small IAM-style evaluator, including the isolation
rule: owner-scoped actions are denied for someone else's resource.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Ship aws/policies/permissions-boundary.json (triple-c-permissions-boundary):
the most any Triple-C role may hold, nothing in IAM.
- environment-admin: role writes require iam:PermissionsBoundary = the
boundary; explicit Denies keep the boundary on roles and the boundary
policy unchanged. Security groups, EFS file systems and KMS keys need
triple-c:component on create and to be modified or destroyed; tagging only
at create or on already-tagged resources.
- workspace-user: RunTask needs an owner-tagged task definition; EFS access
points create/delete by owner tag.
- Both tiers: iam:GetRole and iam:SimulatePrincipalPolicy on the caller's own
${aws:PrincipalArn} only, so SSO callers can be simulated.
- Checks carry the matching context; render() gains {principal}. The test
evaluator resolves policy variables and applies explicit Denies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- workspace-user: TagOwnSecrets refuses component-tagged secrets, plus an
explicit Deny on Tag/Untag/Put/Delete of component-tagged secrets;
CreateAccessPoint only on the component-tagged file system.
- environment-admin: Deny PutRolePermissionsBoundary on triple-c-* roles to
anything but the triple-c boundary; Deny Create/UpdateStack and
CreateChangeSet on triple-c-* stacks with a service role.
- permissions boundary: kms:Decrypt and EFS client access only on
component-tagged keys and file systems; ClientRootAccess dropped (access
points fix the POSIX user).
- README: invariants for phase 4 templates, the actions that are on *, the
phase-6 access-point root note, and the list to verify live.
- Tests: negated operators in the evaluator, both tiers evaluated together,
secret claiming, service-role and boundary-reach cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CreateOwnSecrets requires secretsmanager:KmsKeyId to be a key ARN, and a
workspace user's kms:Encrypt/GenerateDataKey (via Secrets Manager) only
works on component-tagged keys, so secrets can't land on the default
aws/secretsmanager key that the boundary can't decrypt.
- Every workspace statement that sets the owner tag limits aws:TagKeys to
triple-c:owner/project/environment (ForAllValues:StringEquals), so a user
can never set triple-c:component.
- Evaluator: multi-valued context keys and ForAllValues (vacuous when
absent); Check documents repeated keys as one StringList entry.
- README: environment-key invariant and new verify-live entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The AWS-managed aws/secretsmanager key (or a customer key whose key policy
grants account principals) needs no identity-policy Allow, so the tagged-key
Allow alone did not keep user secrets on environment keys. An explicit Deny
on kms:Encrypt / kms:GenerateDataKey* via secretsmanager when the key lacks
triple-c:component does. README claim corrected; verify-live entry added.
Check.context doc now states the StringList rule as a requirement on the
simulation builder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_permissions simulates every check of both tiers against the
caller's resolved principal (bounded to 4 in flight), rendering resources
and literal context values, sending OwnerId and aws:userid as the
caller's user id, and grouping repeated context keys into one StringList
entry. An unsimulatable principal, a denied iam:GetRole or a denied first
simulation falls back to four read-only probes. Results are one row per
action (worst verdict wins).
The trait returns Send futures so the check is Send for Tauri commands.
The module-wide dead_code/unused_imports allow is replaced by allows on
the Task 6 entry points and the re-exports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_permissions now returns Result: credential errors from any call,
and non-denied failures resolving the principal, are errors rather than
a report. Other per-check failures (throttling, network) make the row
Unverified with a note, and a noted row blocks its tier. A probed run
never claims EnvironmentAdmin (R15), and the own-principal check whose
denial forced probing is reported Denied.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Real IAM contradicted the policies in five places, now fixed:
- IAM refuses ${aws:PrincipalArn} as a Resource, so neither tier policy
could be attached. Self-inspection is user/${aws:username} for IAM users
and role/* for role sessions (no role-name variable exists).
- ecs:ExecuteCommand is authorized against the cluster as well as the task;
added an unconditioned cluster statement (the owner rule stays on the task).
- Secrets Manager needs kms:Decrypt with GenerateDataKey on a customer key.
- elasticfilesystem:CreateFileSystem has no resource type (Resource "*").
- ssmmessages:OpenDataChannel on the caller's own sessions (AWS docs).
The permission check now uses adaptive retries for IAM (SimulatePrincipalPolicy
throttled a full check), and the UI no longer says the simulator ignores
permission boundaries (it applies the principal's own; verified).
aws::live_tests (ignored, env-gated) repeats the verification with throwaway
triple-c-e2e-* roles, secrets and keys. New drift tests: every Resource is an
ARN or *, and every policy fits a 6,144-character managed policy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InspectOwnPrincipal allowed iam:GetRole and iam:SimulatePrincipalPolicy on
role/*, letting any workspace user enumerate and simulate every role. IAM
refuses ${aws:PrincipalArn} as a Resource and has no role-name variable, so
the role part is now SSO permission-set roles
(role/aws-reserved/sso.amazonaws.com/*) and triple-c-* roles; IAM users stay
limited to themselves. Callers on other roles are probed and reported
Insufficient; the README says how an admin can add their sign-in roles.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
AWS host phase 3: connect Triple-C to an AWS account and check what it's allowed to do there. Spec:
docs/superpowers/specs/2026-11-13-aws-ecs-host-design.md; plan:docs/superpowers/plans/2026-11-14-aws-connection-permission-check.md.Nothing here starts AWS resources, and it ships no release by itself.
What users get
settings.json.<arn>". An expired or revoked SSO session offers Sign in.iam:SimulatePrincipalPolicyas the caller.Shipped IAM policies (
aws/)workspace-user.json,environment-admin.jsonandpermissions-boundary.json, plusaws/README.mdcovering isolation guarantees, invariants, known gaps for phases 4–6, and the live-verification table.triple-c:ownertag. Users can never settriple-c:component, and environment secrets can't be claimed. User secrets must use the environment KMS key, and an explicit Deny blocks every other key.triple-c-*roles that carry the permissions boundary, and they can't remove, replace or edit that boundary.*resources and the managed-policy size limit.Verified against a real account
cargo test aws::live_tests -- --ignored --test-threads=1withTRIPLEC_AWS_E2E_PROFILE/TRIPLEC_AWS_E2E_REGION. It passes 10/10 using throwawaytriple-c-e2e-*roles and as an SSO admin session.Real IAM disagreed with the policies in five places, all fixed:
${aws:PrincipalArn}is rejected as a Resource, so neither policy could even be attached.kms:Decrypt.CreateFileSystemneeds*.ssmmessages:OpenDataChannelis needed. This one was added from AWS documentation, not a live denial.Items needing real ECS/EFS/EC2 resources are listed in the README for phases 4–6. All test resources were cleaned up; spend was under $0.05.
Notable changes outside the new modules
SettingsStore::updatenow saves before replacing the in-memory copy, so a failed save no longer leaves memory and disk diverged. A newmodifydoes a read-modify-save under the lock.update_settingskeepshostsas stored, the same as marketplace fields; import re-applies imported hosts.run_sso_loginpasses--profile=<name>as a single argv element.aws-sdk-sts,-iam,-cloudformationand-secretsmanager, plusaws-sdk-kmsas a dev-dependency. They aredefault-features = false, and the legacy rustls 0.21 stack is still absent.Design rulings made during implementation (recorded in the spec)
triple-c-permissions-boundaryis a phase-4 design item.triple-c-*roles. Users signing in through other roles fall back to probes; the README explains how an admin can add them.For phase 4
workspace-user.jsonis about 30 characters under the 6,144-character managed-policy limit, so it must be split.ecs:Describe*.Testing
cargo test: 1049 passed.vitest: 1194 passed.tscclean, and the build adds no new warnings. Each task was built by a subagent and reviewed for spec and quality, followed by a whole-branch review, and every finding was fixed.🤖 Generated with Claude Code
aws/policies/{workspace-user,environment-admin}.json are the IAM policies for the two tiers; aws::policies embeds them and holds one representative simulator check per action. Tests keep table and JSON in lock-step and run each check through a small IAM-style evaluator, including the isolation rule: owner-scoped actions are denied for someone else's resource. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>- Ship aws/policies/permissions-boundary.json (triple-c-permissions-boundary): the most any Triple-C role may hold, nothing in IAM. - environment-admin: role writes require iam:PermissionsBoundary = the boundary; explicit Denies keep the boundary on roles and the boundary policy unchanged. Security groups, EFS file systems and KMS keys need triple-c:component on create and to be modified or destroyed; tagging only at create or on already-tagged resources. - workspace-user: RunTask needs an owner-tagged task definition; EFS access points create/delete by owner tag. - Both tiers: iam:GetRole and iam:SimulatePrincipalPolicy on the caller's own ${aws:PrincipalArn} only, so SSO callers can be simulated. - Checks carry the matching context; render() gains {principal}. The test evaluator resolves policy variables and applies explicit Denies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Real IAM contradicted the policies in five places, now fixed: - IAM refuses ${aws:PrincipalArn} as a Resource, so neither tier policy could be attached. Self-inspection is user/${aws:username} for IAM users and role/* for role sessions (no role-name variable exists). - ecs:ExecuteCommand is authorized against the cluster as well as the task; added an unconditioned cluster statement (the owner rule stays on the task). - Secrets Manager needs kms:Decrypt with GenerateDataKey on a customer key. - elasticfilesystem:CreateFileSystem has no resource type (Resource "*"). - ssmmessages:OpenDataChannel on the caller's own sessions (AWS docs). The permission check now uses adaptive retries for IAM (SimulatePrincipalPolicy throttled a full check), and the UI no longer says the simulator ignores permission boundaries (it applies the principal's own; verified). aws::live_tests (ignored, env-gated) repeats the verification with throwaway triple-c-e2e-* roles, secrets and keys. New drift tests: every Resource is an ARN or *, and every policy fits a 6,144-character managed policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>InspectOwnPrincipal allowed iam:GetRole and iam:SimulatePrincipalPolicy on role/*, letting any workspace user enumerate and simulate every role. IAM refuses ${aws:PrincipalArn} as a Resource and has no role-name variable, so the role part is now SSO permission-set roles (role/aws-reserved/sso.amazonaws.com/*) and triple-c-* roles; IAM users stay limited to themselves. Callers on other roles are probed and reported Insufficient; the README says how an admin can add their sign-in roles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>