Skip to content

🤖🤖🤖 New Actions: aws_agentregistry_submit_registry_record_for_approval and aws_agentregistry_update_registry_record_status - #49931

Open
pablo19sc wants to merge 10 commits into
hashicorp:mainfrom
pablo19sc:f-agentregistry-record-actions
Open

🤖🤖🤖 New Actions: aws_agentregistry_submit_registry_record_for_approval and aws_agentregistry_update_registry_record_status#49931
pablo19sc wants to merge 10 commits into
hashicorp:mainfrom
pablo19sc:f-agentregistry-record-actions

Conversation

@pablo19sc

Copy link
Copy Markdown
Contributor

Rollback Plan

If a change needs to be reverted, we will publish an updated version of the library.

Changes to Security Controls

Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.

No. Both actions call existing Agent Registry APIs (SubmitRegistryRecordForApproval, UpdateRegistryRecordStatus) with the caller's credentials and add no new permissions. They preserve the service's publisher/curator separation: submission and approval remain distinct operations that users can bind to different provider identities.

Description

Agent Registry records are created in DRAFT and are not discoverable until approved. Nothing in the provider can move a record out of DRAFT today, so every record created with aws_agentregistry_registry_record (#49918) is invisible to consumers. This also affects registries configured with auto_approval_rules = ["APPROVE_ALL"]: verified against the API, auto-approval does not bypass submission, it only changes where submission lands.

This PR includes two Terraform Actions covering the record approval lifecycle.

  • aws_agentregistry_submit_registry_record_for_approval (publisher side) moves a DRAFT record into the approval workflow. Designed to run on the record's after_create and after_update events, since any content update returns a record to DRAFT and it must be resubmitted.
  • aws_agentregistry_update_registry_record_status (curator side) approves or rejects a PENDING_APPROVAL record, or deprecates a record. status is restricted to APPROVED, REJECTED, DEPRECATED, the only targets the API accepts.

With an auto-approval registry, records become discoverable on every apply with one action_trigger and no manual steps. With manual approval, the publisher's apply leaves the record PENDING_APPROVAL and a curator (typically a separate configuration and IAM principal) invokes the status action with terraform apply -invoke=.... Both actions require Terraform 1.14 or later, consistent with the provider's existing actions.

Why two actions in one PR

The contribution guide asks for one resource per PR, and I want to be explicit about why this PR deliberately contains two actions.

They are two halves of a single state machine, and neither is complete or fully reviewable alone:

  • The status action cannot be exercised without the submit action. APPROVED and REJECTED are only reachable from PENDING_APPROVAL, which only submission produces. Its acceptance tests chain both actions on one trigger; a standalone PR would have no way to test approve/reject.
  • The submit action's error handling for REJECTED records is only meaningful once rejection exists. Reviewing its recovery-path messaging in isolation means reviewing behavior nothing can yet trigger.
  • The transition matrix (which states each action must treat as no-op, error, or proceed) was established empirically in one test session against the API and is encoded across both files. Splitting them risks the two halves drifting on edge cases, and forces a reviewer to hold the same state machine in mind across two PRs anyway.

The shared code is one small helper (waitRegistryRecordSettled, ~25 lines). The two actions are otherwise independent files, so the diff still reads one action at a time, and the commits are split one per action for that reason.

Why actions rather than a resource or a status argument

Considered and rejected, in case reviewers wonder:

  • A status argument on the record resource would fight the governance workflow. If a curator rejects a record out-of-band, the next plan shows REJECTED → APPROVED as drift and the apply fails, because that transition is invalid. It would also merge publisher and curator permissions into one principal.
  • A standalone *_approval resource has no remote object to import, read, or delete, and has the same drift problem after every record update. Terraform would try to re-approve records a human had rejected.
  • Approval is a decision performed once when a human (or an auto-approval rule) says so, not a desired state Terraform should reconcile. That is what actions are for.

Implementation notes

Behavior below was verified against the live API before implementation; the notes record what the tests rely on.

  • Submit reads the record first and branches on status. DRAFT submits. PENDING_APPROVAL and APPROVED are no-ops, which matters because the API is asymmetric here: resubmitting a PENDING_APPROVAL record succeeds, resubmitting an APPROVED record fails with a ValidationException. REJECTED and DEPRECATED return errors describing the recovery path (update content to return to DRAFT; deprecation is terminal). CREATING/UPDATING are waited on, which is the normal case when triggered from after_update.
  • The status action no-ops when the record already has the requested status, because a repeated status update succeeds but overwrites status_reason, erasing the original curator's rationale.
  • Both actions are synchronous at the API level; timeout only bounds the pre-action settle wait (default 600s).
  • Examples reference the record resource directly rather than the caller symbol, which is only available in HCP Terraform Stacks on Terraform 1.16+. Noted in the docs.
  • DEPRECATED is documented with a warning as irreversible: no further submission, approval, or content update is possible, only deletion.

AI Usage

This PR was developed with AI assistance. The AI ran the exploratory API tests that established the record status transition matrix, generated both action implementations, their acceptance tests, and documentation following the provider's existing action patterns (aws_ec2_stop_instance, aws_codebuild_start_build), and ran unit tests, make gen, make quick-fix, and make swissshepherd. I reviewed the code and the design, and ran all acceptance tests against a real AWS account. I take full responsibility for the change.

Relations

Relates #48694
Depends on #49918
Depends on #49922

References

Output from Acceptance Testing

Terraform v1.14.6.

% make testacc PKG=agentregistry P=2 TESTS='TestAccAgentRegistrySubmitRegistryRecordForApprovalAction_|TestAccAgentRegistryUpdateRegistryRecordStatusAction_'
--- PASS: TestAccAgentRegistryUpdateRegistryRecordStatusAction_approve (109.25s)
--- PASS: TestAccAgentRegistrySubmitRegistryRecordForApprovalAction_manualApproval (114.46s)
--- PASS: TestAccAgentRegistryUpdateRegistryRecordStatusAction_deprecate (107.58s)
--- PASS: TestAccAgentRegistrySubmitRegistryRecordForApprovalAction_resubmitAfterUpdate (120.21s)
--- PASS: TestAccAgentRegistrySubmitRegistryRecordForApprovalAction_autoApproval (113.00s)
--- PASS: TestAccAgentRegistryUpdateRegistryRecordStatusAction_reject (108.25s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/agentregistry      345.442s

Add the aws_agentregistry_registry_record resource supporting all four
record types (MCP, AGENT, SKILL, CUSTOM) with typed descriptors, URL
source synchronization with IAM and OAuth credential providers, tags,
resource identity, and two-part (registry_id,record_id) import.

UpdateRegistryRecord wraps mutable fields in Updated* optional-value
types; updates send a full-desired-state patch so removed descriptor
fields are unset. trigger_synchronization is intentionally not exposed
as it is a non-convergent action flag.
The UpdateRegistryRecord API takes RecordVersion as a plain string with
no Updated* wrapper, so there is no way to clear a version once set.
Removing the argument leaves the previous value in place and produces a
persistent difference.
Look up a registry record by registry ID and record ID, reusing the
resource's descriptor models and finder. Also exposes the read-only
status, status_reason, registry_arn, created_at and updated_at fields
that the resource does not manage.
Comparing the whole descriptors object fails because unset descriptor
types are null lists in resource state but empty lists in the data
source. Compare the custom.data leaf and the list size instead,
matching the registry data source test approach.
The test-naming and tflint jobs failed in their setup steps with
apt-get 'Hash Sum mismatch' errors fetching the Chrome apt index on
the runner image, before running any checks. No code changes are
needed.
Records are created in DRAFT and are not discoverable until approved.
Neither the record resource nor a registry's auto-approval rules submit
a record; this action does, and is intended to run on the record's
after_create and after_update lifecycle events since any content update
returns the record to DRAFT.

The action reads the record first: DRAFT is submitted, PENDING_APPROVAL
and APPROVED are no-ops (the API rejects resubmission of an APPROVED
record), REJECTED and DEPRECATED return descriptive errors with the
recovery path, and CREATING/UPDATING are waited on before proceeding.
Curator-side companion to the submit action: approve or reject a
PENDING_APPROVAL record, or deprecate a record. The status argument is
restricted to APPROVED, REJECTED and DEPRECATED, matching the targets
the API accepts. When the record already has the requested status the
action returns without calling the API, since repeating a status update
overwrites the existing status reason.
@pablo19sc
pablo19sc requested a review from a team as a code owner September 9, 2026 21:10
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Community Guidelines

This comment is added to every new Pull Request to provide quick reference to how the Terraform AWS Provider is maintained. Please review the information below, and thank you for contributing to the community that keeps the provider thriving! 🚀

Voting for Prioritization

  • Please vote on this Pull Request by adding a 👍 reaction to the original post to help the community and maintainers prioritize it.
  • Please see our prioritization guide for additional information on how the maintainers handle prioritization.
  • Please do not leave +1 or other comments that do not add relevant new information or questions; they generate extra noise for others following the Pull Request and do not help prioritize the request.

Pull Request Authors

  • Review the contribution guide relating to the type of change you are making to ensure all of the necessary steps have been taken.
  • Whether or not the branch has been rebased will not impact prioritization, but doing so is always a welcome surprise.

@github-actions github-actions Bot added needs-triage Waiting for first response or review from a maintainer. documentation Introduces or discusses updates to documentation. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure. sweeper Pertains to changes to or issues with the sweeper. generators Relates to code generators. service/agentregistry Issues and PRs that pertain to the agentregistry service. size/XL Managed by automation to categorize the size of a PR. partner Contribution from a partner. labels Sep 9, 2026
@justinretzolk justinretzolk added new-action Introduces a new action. and removed needs-triage Waiting for first response or review from a maintainer. labels Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Introduces or discusses updates to documentation. generators Relates to code generators. new-action Introduces a new action. partner Contribution from a partner. service/agentregistry Issues and PRs that pertain to the agentregistry service. size/XL Managed by automation to categorize the size of a PR. sweeper Pertains to changes to or issues with the sweeper. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants