Skip to content

fix(terraform): grant intents Lambda dynamodb:ConditionCheckItem - #569

Merged
jeromevdl merged 1 commit into
mainfrom
fix/intents-condition-check-permission
Oct 15, 2026
Merged

jeromevdl merged 1 commit into
mainfrom
fix/intents-condition-check-permission

Conversation

@jeromevdl

Copy link
Copy Markdown
Collaborator

Problem

Answering an engine-owned human gate (POST /projects/{projectId}/intents/{intentId}/gates/{humanTaskId}/answer) returns HTTP 500. The intents Lambda logs:

AccessDeniedException: ... is not authorized to perform: dynamodb:ConditionCheckItem on resource: .../table/<project>-v2-executions-<env> because no identity-based policy allows the dynamodb:ConditionCheckItem action

answerHumanTask / answerHumanTaskWithSteering write a TransactWriteItems that fences run and stage ownership with ConditionCheck entries (humanTaskAnswerOwnershipChecks in lambda/shared/v2-process-store.js). DynamoDB authorizes every ConditionCheck in a transaction as dynamodb:ConditionCheckItem. The intents role grants TransactWriteItems but not ConditionCheckItem, so the transaction is rejected whenever the gate carries an orchestratorRunId, which every engine-opened gate does.

When it was introduced

  • Code: commit 663962e ("fix(orchestrator): open owned engine gates atomically", 2026-09-22). It added the ownership ConditionChecks to the gate-answer transaction. dc9d3eb (2026-09-28) later refactored them without changing the transaction.
  • Shipped to main in fix: recover Kiro intents after quota exhaustion and lost sessions #466 (fix/463-intent-recovery), merged 2026-10-14.
  • The Terraform policy for the intents role was never updated, so any stack deployed from main since 2026-10-14 cannot answer engine gates.
  • The test suite didn't catch it because DynamoDB Local doesn't enforce IAM.

Fix

Add dynamodb:ConditionCheckItem to the v2 process-table statement of aws_iam_role_policy.intents. The AgentCore role already grants it. No other role on that table issues ConditionChecks: over the last 14 days, a deployed stack logged no other AccessDenied errors on the table.

Impact / rollout

  • IAM-only change. Applying Terraform unblocks the affected gates immediately, with no Lambda redeploy.
  • Failed answers wrote nothing because the transaction was rejected as a whole. Users can re-submit the same answer after the apply.

Validation

  • terraform -chdir=terraform fmt -check -recursive passes.
  • terraform validate was not run locally (it requires the CI local-backend override); left to the Terraform CI workflow.

Gate answers write a TransactWriteItems that fences run and stage
ownership with ConditionCheck entries (humanTaskAnswerOwnershipChecks,
added in 663962e via #466). DynamoDB authorizes each ConditionCheck as
dynamodb:ConditionCheckItem, which the intents role never had, so every
answer to an engine gate failed with AccessDeniedException (HTTP 500).
@jeromevdl
jeromevdl merged commit 264754b into main Oct 15, 2026
7 checks passed
JWThewes added a commit that referenced this pull request Oct 27, 2026
The completion work adds the first orchestrator-issued transactions with
ConditionCheck entries: updateForRun (integration writes, skip receipts,
fan-out unit-plan decisions), deleteWorkflowCheckpoint with a run fence, and
finalizeUnitCompletion with its unit-plan snapshot check. DynamoDB authorizes
each ConditionCheck as dynamodb:ConditionCheckItem, which the orchestrator role
never had. The call fails with AccessDeniedException rather than a conditional
failure, so the orchestrator ends the intent FAILED with completion_unverified.

DynamoDB Local does not enforce IAM, so the behavior tests cannot see this. Add
a policy test, as the AgentCore role already has, and grant the action on the
process table statement. Same class of failure as #569 for the intents role.
@eipasteur

eipasteur commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

TEST PURPOSES ONLY — DO NOT TAKE INTO ACCOUNT.

Automatically computed PR review signals (deterministic)

No production JS/TS in scope; the quality analyzer does not assess Terraform or IAM.


Isobar map

PR impact map

Fixed repository map: red marks changed files; green marks static name matches or import links across components. These links indicate possible reach, not proven runtime impact or a risk grade.

Isobar by r3al1tym.

Signals
  • A: terraform/modules/api/lambda/main.tf — static reach unavailable.
  • Revision: 29ab438; updated 2026-10-27 17:28 UTC.
Legend
  • ○ modified · ◇ added · × deleted. Blue markers: tests; gray markers: documentation.
  • Solid green: import-linked name matches. Dotted green: broader file-level import fallback. Both are static evidence, not proven execution.

jeromevdl pushed a commit that referenced this pull request Oct 29, 2026
* Prevent incomplete intents from reaching success and publication

A dependent walking skeleton or blocked-only lanes could let an intent
finish while required current-plan work remained. Validate skeleton and
wave selection, halt on unresolved lanes, and use one shared completion
evaluator (lambda/shared/unit-completion.js) at section fan-in, final
success and initial publication for new histories.

Required integration writes are no longer best-effort: an unrecorded
integration stops the lane, a lost response is reconciled from persisted
state, and final status commits with its completion receipt under run,
status, META revision and unit-plan conditions. Marker-absent histories
keep their durable operation sequence.

Review corrections included: re-promotion reselects a valid skeleton for a
regenerated DAG, halt prompts count failed and blocked lanes separately,
rewind/recompose return 409 execution_changed when retirement loses run
ownership, and intent DELETE matches only the intent route.

Squashes the reviewed restructure (originally 8018321..a870e6b) onto
main; the deferred preservation-recovery work is not included.

* Preserve legacy integrated units and serial completion presentation

* Use one new completion policy above marker-absent legacy replay

* fix: classify recorded aborts before legacy workflow resolution

* fix(terraform): grant v2-orchestrator dynamodb:ConditionCheckItem

The completion work adds the first orchestrator-issued transactions with
ConditionCheck entries: updateForRun (integration writes, skip receipts,
fan-out unit-plan decisions), deleteWorkflowCheckpoint with a run fence, and
finalizeUnitCompletion with its unit-plan snapshot check. DynamoDB authorizes
each ConditionCheck as dynamodb:ConditionCheckItem, which the orchestrator role
never had. The call fails with AccessDeniedException rather than a conditional
failure, so the orchestrator ends the intent FAILED with completion_unverified.

DynamoDB Local does not enforce IAM, so the behavior tests cannot see this. Add
a policy test, as the AgentCore role already has, and grant the action on the
process table statement. Same class of failure as #569 for the intents role.
@jeromevdl jeromevdl added area/infra Terraform, installer and deployment size/XS < 50 changed lines (lockfiles excluded) fix Bug fix: PR title starts with fix: or fix(scope): labels Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/infra Terraform, installer and deployment fix Bug fix: PR title starts with fix: or fix(scope): size/XS < 50 changed lines (lockfiles excluded)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants