ci(deps): bump LerianStudio/github-actions-shared-workflows/.github/workflows/pr-validation.yml from 1.10.2 to 1.11.0#3
Conversation
…orkflows/pr-validation.yml Bumps [LerianStudio/github-actions-shared-workflows/.github/workflows/pr-validation.yml](https://github.com/lerianstudio/github-actions-shared-workflows) from 1.10.2 to 1.11.0. - [Release notes](https://github.com/lerianstudio/github-actions-shared-workflows/releases) - [Changelog](https://github.com/LerianStudio/github-actions-shared-workflows/blob/main/docs/release-workflow.md) - [Commits](LerianStudio/github-actions-shared-workflows@v1.10.2...v1.11.0) --- updated-dependencies: - dependency-name: LerianStudio/github-actions-shared-workflows/.github/workflows/pr-validation.yml dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
LabelsThe following labels could not be found: Please fix the above issues or remove invalid values from |
|
Consider updating CHANGELOG.md to document this change. If this change doesn't need a changelog entry, add the |
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Looks like LerianStudio/github-actions-shared-workflows/.github/workflows/pr-validation.yml is up-to-date now, so this is no longer needed. |
* test(governance): add failing tests for actor_mapping pseudonymization bypass fix [TDD-RED]
Encodes post-fix contract from Taura Security pentest finding (28/04/2026):
actor_mapping identity fields become append-only; pseudonymization is
irreversible per actor_id; mutation attempts surface as HTTP 409 via a new
ErrActorMappingImmutable sentinel.
Failing tests cover:
- Service: CreateOrGetActorMapping (renamed from UpsertActorMapping) for
AC1 (new actor), AC2 (idempotent no-op), AC3/AC4 (different email/name),
AC5 (pentest PoC: PUT over [REDACTED]).
- Repository sqlmock: INSERT ... ON CONFLICT DO NOTHING RETURNING contract,
post-INSERT SELECT comparison path, ErrActorMappingImmutable on divergence.
- HTTP handler: PUT mapped to 200 (create / idempotent) or 409 (mutation /
redacted overwrite attempt).
Build is intentionally RED until Gate 0.2 (TDD-GREEN) introduces:
- command.ErrActorMappingImmutable
- ActorMappingUseCase.CreateOrGetActorMapping
- actormapping.ErrActorMappingImmutable
- INSERT ... ON CONFLICT DO NOTHING SQL + compare-or-fail logic
- Handler error-to-409 mapping
* fix(governance): make actor_mapping identity fields immutable post-creation [TDD-GREEN]
Addresses Taura Security pentest finding (28/04/2026): pseudonymization
of actor mappings could be silently reverted via subsequent PUT requests.
The fix introduces:
- ErrActorMappingImmutable sentinel in domain/errors, re-exported by the
adapter and service layers so errors.Is works across the layer boundary
without violating depguard service-no-adapters
- INSERT ... ON CONFLICT DO NOTHING + transaction-scoped SELECT compare
at the SQL layer, replacing the COALESCE-based upsert that allowed
plaintext PII to overwrite [REDACTED] values; the same-transaction
compare closes the TOCTOU window
- CreateOrGetActorMapping service method documenting the new append-only
semantics; UpsertActorMapping kept as a thin wrapper for the existing
HTTP handler
- 409 Conflict response on PUT attempts that mutate display_name or email,
surfaced via the slug governance_actor_mapping_immutable
- Idempotent no-op for PUT with identical payload (HTTP PUT semantics
preserved, updated_at unchanged)
- Swagger documentation of the 409 response
Defense-in-depth: validation enforced at both service and SQL layers.
Identity-mutation failures use HandleSpanBusinessErrorEvent so they don't
inflate 5xx dashboards. The previous test
TestUpsert_PreservesExistingFieldsWhenInputIsNil exercised the vulnerable
COALESCE behavior; it is replaced by
TestUpsert_PartialPayloadRejectedWhenStoredFieldsDiffer covering the new
contract.
* test(governance): add fuzz tests for actor_mapping immutability invariants
Adds three property-based fuzz targets covering the helpers that gate the
pseudonymization-bypass fix (Taura Security pentest, 28/04/2026):
- FuzzStringPtrEqual asserts reflexivity, symmetry, and the documented
nil/empty/byte-equality semantics. Any drift here would silently allow
a mutation through the conflict path of insertOrCompare.
- FuzzActorMappingPIIDiffers asserts reflexivity, symmetry, and the
nil-arg "differs" contract — the invariants the immutability check
depends on.
- FuzzNewActorMapping asserts the XOR(success, error) contract of the
constructor and validates the trimming/length sentinels never panic
under adversarial UTF-8, NUL bytes, or overlong inputs.
Each target ran for 10s with no findings (10 seed inputs total, ~2.5M
executions combined).
* test(governance): add property tests for actor_mapping immutability invariants
Gate 5 of fix-actor-mapping-pseudonymization-bypass. Encodes domain
invariants from the Taura Security pentest finding (28/04/2026) as
testing/quick property checks (MaxCount=1000 per property).
Properties:
- IsRedacted is well-defined (biconditional vs hand-coded reference),
partial-redaction always false, nil receiver returns false.
- Pseudonymization is irreversible — after a row enters [REDACTED],
no Upsert/CreateOrGetActorMapping puts plaintext PII back on disk
until DELETE clears the row.
- CreateOrGetActorMapping is idempotent for identical args.
- Mutation of display_name OR email on an existing row returns
ErrActorMappingImmutable and leaves the stored row untouched.
Uses a hand-rolled statefulFakeRepository that mirrors the post-fix
INSERT...ON CONFLICT DO NOTHING + SELECT + compare semantics from
the postgres adapter, driven by a deterministic LCG-decoded trace
generator.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(governance): add integration tests for actor_mapping immutability and TOCTOU resistance
Gate 6 WRITE phase for fix-actor-mapping-pseudonymization-bypass.
Adds 9 testcontainers-backed integration tests in the actor_mapping
adapter package covering the post-fix INSERT ... ON CONFLICT DO NOTHING +
SELECT compare contract end-to-end against real PostgreSQL:
AC1 NewActor_PersistsAndReturnsEntity
AC2 IdempotentSameValues_NoMutation (verifies updated_at pinned)
AC3/4 DifferentPayload_ReturnsImmutable (row preserved)
AC5 OverRedacted_ReturnsImmutable (plaintext-over-redacted PoC)
AC5 OverRedacted_ConcurrentPlaintextAttacks_AllFail (race PoC)
AC7 DeleteAfterPseudonymize_Succeeds
AC8 ConcurrentDifferentPayloads_NoMutation (load-bearing race)
AC8 ConcurrentIdenticalPayloads_AllSucceedIdempotently
AC8 ConcurrentFreshActor_OneInsertsRestSeeWinner (TOCTOU on fresh ID)
Tests use the shared tests/integration.TestHarness which spins
Postgres 17 + Valkey 8 + RabbitMQ via testcontainers, runs the
embedded migrations, and provides a tenant-scoped InfrastructureProvider.
Tests authored only; orchestrator will execute at cycle-end.
* test(governance): adjust integration tests to match new immutability contract
Two pre-existing tests in tests/integration/governance/actor_mapping_test.go
encoded the PRE-FIX vulnerable behaviour of the actor_mapping upsert path
(COALESCE-based UPDATE on conflict) and would fail under the new
immutability contract introduced to close the pseudonymization-bypass
finding.
- Removed TestIntegration_Governance_ActorMapping_UpsertUpdatesExisting:
redundant with TestIntegration_ActorMappingImmutability_DifferentPayload_ReturnsImmutable
in internal/governance/adapters/postgres/actor_mapping/actor_mapping_immutability_integration_test.go,
which already pins "existing row + different payload → ErrActorMappingImmutable
+ row unchanged" end-to-end.
- Reframed TestIntegration_Governance_ActorMapping_UpsertPreservesExistingFieldWhenOmitted
into TestIntegration_Governance_ActorMapping_UpsertPartialPayloadIsRejected:
the new path has no COALESCE escape hatch, so a partial PUT (different
display_name, nil email) against an existing row must surface
ErrActorMappingImmutable and leave the persisted row untouched. This
documents the no-COALESCE contract from the package-level integration
harness.
Pure test-side adjustment; no production code touched.
* test(governance): add chaos tests for actor_mapping immutability under DB failure injection
Authors five Toxiproxy-driven chaos scenarios under build tag `chaos` to
verify the post-fix Upsert path (INSERT ON CONFLICT DO NOTHING + in-tx
SELECT-compare) keeps its immutability guarantee when Postgres misbehaves:
1. Connection drop mid-transaction against an existing row → caller
errors out, row UNCHANGED.
2. Connection drop / cancellation around a fresh-actor INSERT → either
the full payload landed or the row is absent; never partial.
3. Pseudonymized [REDACTED] row + 1s latency + concurrent plaintext
attackers → zero successes, row remains [REDACTED]/[REDACTED].
4. PG proxy fully disabled → repo returns a wrapped error, no panic,
no nil-without-error, no hang (10s watchdog).
5. Disable / re-enable proxy → idempotent re-PUT recovers, persisted
row matches the submitted payload exactly.
Tests WRITE-only at this gate; execution is deferred to cycle-end per
gate cadence. Reuses tests/chaos harness (ChaosHarness, InjectPGResetPeer,
InjectPGLatency, DisablePGProxy, DirectDB) — no new infrastructure.
* fix(governance): record handler 409 as span business event
The actor_mapping immutable handler was using LogSpanError for the 409
Conflict path, which calls libOpentelemetry.HandleSpanError and marks the
span as failed. A 409 raised by the post-fix immutability contract is a
client-side mistake (the persisted row is untouched), not an
infrastructure or server fault — it MUST not pollute the error budget.
Adds sharedhttp.LogSpanBusinessEvent which records the event via
libOpentelemetry.HandleSpanBusinessErrorEvent (no error attribution) and
still emits the SafeError log line. Switches writeConflict to use it and
updates the docstring to match.
Refs Gate 8 review finding H-1.
* feat(errors): register governance_actor_mapping_immutable in catalog
Adds CodeGovernanceActorMappingImmutable = "MTCH-0604" to the product
error code table and wires the governance_actor_mapping_immutable slug
into the shared HTTP error catalog so 409 responses from the actor
mapping immutability path surface the stable product code instead of the
generic conflict fallback. Clients can now branch on MTCH-0604 to
distinguish the pseudonymization-bypass rejection from other conflict
modes.
Refs Gate 8 review finding M-1.
* test(governance): tighten sqlmock regex and decode 409 response body
H-2: The sqlmock regex helpers used .* between SQL tokens, which would
silently accept arbitrary SQL injected between, say, DO NOTHING and
RETURNING. Replaces .* with \s+ where the gap is whitespace, and bounds
the column-list and VALUES segments with [^)]* so injection inside
parentheses is also rejected. Removes the dead `regexp` import that only
existed to satisfy a `var _ = regexp.MustCompile` compile-time guard.
M-2: The three immutability handler tests asserted only the HTTP status
code, not the response body. Decodes the JSON body and verifies the
product code equals constant.CodeGovernanceActorMappingImmutable
(MTCH-0604) and the message describes the immutability constraint. This
closes the loophole where the handler could return 409 with a generic
"conflict" payload and the test would still pass.
Also drops the dead `var _ = http.StatusOK` compile-time guard from the
handler test file and updates the file-header comment to "Pins post-fix
contract" (the GREEN phase has shipped — the TDD-RED header is stale).
Pretty-prints the fuzz seed corpus via gofmt (no behavior change).
Refs Gate 8 review findings H-2, M-2, L1, L2.
* test(governance): fix irreversibility property with independent oracle
The pseudonymization-irreversibility property tracked `redacted` by
consulting `snap.IsRedacted()` after every operation, which collapsed
the invariant into a tautology: the model state was derived from the
repository state, so the assertion `if redacted: require
snap.IsRedacted()` was always trivially true.
Reworks the state oracle so `redacted` is set ONLY by opPseudonymize on
an existing row and cleared ONLY by opDelete or the delete step of
opRecreate. The repository snapshot is now used exclusively for
invariant assertions, never to derive the oracle's flag. The property
now genuinely fails if a future regression allows an Upsert/Create call
to overwrite a [REDACTED] row.
Refs Gate 8 review finding H-3.
* test(chaos): serialize actor_mapping chaos tests and enforce immutable bucket floor
H-4: The five actor_mapping chaos tests called truncateActorMappingDirect
without acquiring the shared chaos harness mutex (h.testMu). If the chaos
suite is ever run with t.Parallel enabled, the tests would cross-
contaminate each other's Toxiproxy injections and direct-DB state.
Exposes a new ChaosHarness.LockTest(t) helper that acquires h.testMu and
registers t.Cleanup to release. The five actor_mapping chaos tests now
call h.LockTest(t) at the top so they are mutually exclusive with each
other (and with ResetDatabase-using tests) regardless of -parallel.
H-5: PseudonymizedRowUnderLatency_StillRejectsAttacker tolerated runs
where 100% of attacker calls fell into the timeout/otherErrors buckets,
masking a real bypass behind a degenerate environment. Adds a
require.GreaterOrEqual(immutableHits, 1) assertion so at least one
attacker MUST observe ErrActorMappingImmutable for the scenario to
count as a valid pass.
Refs Gate 8 review findings H-4, H-5.
* test(e2e): align actor_mapping update journey with immutability contract
The previous TestActorMapping_Update PUT-ed an existing actor_id with a
different display_name and asserted the row was updated — that
asserted the pre-fix mutation behavior, which the post-fix contract now
rejects with 409.
Replaces the test with two scenarios that pin the new contract:
* TestActorMapping_IdempotentSamePayload — second PUT with identical
display_name/email returns 200 and echoes the same row.
* TestActorMapping_MutationReturnsConflict — second PUT with a
different display_name returns 409 with the
governance_actor_mapping_immutable product code (MTCH-0604); the
persisted row is unchanged.
Uses the existing client.APIError.IsConflict / ProductCode helpers; no
changes to tests/client/governance.go are required.
Refs Gate 8 review finding C-1.
* docs(governance): update Upsert contract doc and table COMMENT for immutability
M-3: The ActorMappingRepository interface doc still described Upsert as
"creates or updates an actor mapping" — that wording matches the pre-fix
mutable contract. Updates both the type-level and Upsert-level doc
comments to reflect the post-fix append-only contract: identity fields
cannot be mutated in place; mismatching payloads return
ErrActorMappingImmutable; pseudonymization and right-to-erasure remain
the only state transitions.
M-4: Migration 000001 still carries the original COMMENT ON TABLE
text claiming the table is "Mutable". Adds migration 000033 to update
the COMMENT to describe the append-only contract and the
governance_actor_mapping_immutable (MTCH-0604) rejection. Migration
000001 itself is left untouched per the standard rule against editing
applied migrations. The .down.sql restores the pre-fix COMMENT text.
Refs Gate 8 review findings M-3, M-4.
* docs(governance): fix Gate 8 review findings M-1, M-2, M-3
M-1: remove dead actorID empty-string reject branch in
actor_mapping_immutability_property_test idempotency test. actorID is
built from a uint16 seed so it can never be empty; the guard was dead
code flagged by ring:test-reviewer.
M-2: collapse dead conditional in the irreversibility oracle's
opCreate/opRecreate arm. Both branches of "if ok && !redacted else if ok"
performed the same assignment; rewrite as a single "if ok" with explicit
comment about redacted-flag ownership (set by opPseudonymize, cleared by
opDelete/opRecreate-delete) to keep the oracle independent of repo state
per commit 9a2dd57.
M-3: update ActorMapping entity docstring to reflect the post-fix
append-only contract. Old text claimed the table was "mutable by design
for GDPR compliance"; new text documents append-only identity fields,
the ErrActorMappingImmutable / MTCH-0604 / HTTP 409 rejection, and the
two allowed state transitions (Pseudonymize and DELETE), with a pointer
to migration 000033.
M-4 (skipped): CHANGELOG entry was not added manually because the repo
uses semantic-release with @semantic-release/changelog plugin; manual
edits would be overwritten. The release-engineering gap (no
BREAKING CHANGE: footer in any branch commit, so semver may emit only
a patch bump for a public-API breaking change) is surfaced for the
release owner as a follow-up; it is out of Gate 8 cleanup scope.
Refs Gate 8 review (ring:codereview iteration 1).
* chore(dev-cycle): commit cycle artifacts for fix/governance-actor-mapping-pseudonymization-bypass
Persists the dev-cycle state file and task spec as audit artifacts for
the actor_mapping pseudonymization bypass fix.
Cycle summary:
- Source: docs/tasks/fix-actor-mapping-pseudonymization-bypass.md
- Origin: Pentest Taura Security 28/04/2026
- Task: T-001 (1 subtask: ST-001-01) — completed
- Total commits in branch: 17 (16 + this artifact commit)
- Gates closed (lean backend flow):
* Gate 0 (Implementation): TDD-RED 430e81b, TDD-GREEN 4f595b1,
plus fuzz/property/integration/chaos/e2e/observability/migration
work consolidated under the lean flow's Gate 0 quality umbrella
* Gate 8 (Codereview): 10/10 reviewers PASS, iteration 1, 4 MEDIUMs
resolved (M-1/M-2/M-3 fixed in commit 2cbee71, M-4 deferred to
release engineering)
* Gate 9 (Validation): user APPROVED, all 10 ACs verified
* Gate 0.5D (Migration Safety): PASS — migration 000033 is
documentation-only (COMMENT ON TABLE), zero schema mutation,
fully reversible
State file is preserved as the cycle audit record.
Refs: /ring:dev-cycle resume session 2026-05-14.
* chore(dev-cycle): mark cycle as completed
Final cycle close for fix-actor-mapping-pseudonymization-bypass-2026-05-13.
- status: in_progress → completed
- feedback_loop_completed: false → true
- task T-001: in_progress → completed
- completed_at: 2026-05-14T15:55:00Z
ring:dev-report dispatch deferred for context economy; can be re-run
via /ring:dev-report when continuous-improvement metrics are desired.
All gates closed (lean backend flow):
- Gate 0 (Implementation): ✓
- Gate 8 (Codereview, 10/10 PASS): ✓
- Gate 9 (Validation, user APPROVED): ✓
- Gate 0.5D (Migration safety): ✓
* chore(governance): apply CodeRabbit local review findings
Applies all 7 findings from the local CodeRabbit review against the
fix-actor-mapping-pseudonymization-bypass branch before opening PR.
Grupo A — Swagger field name (3 findings, 1 root cause):
- handlers_actor_mapping.go: replace display_name with displayName in
the Swagger @description and doc comment for UpsertActorMapping. The
request JSON field is camelCase per the DTO, so the snake_case
description would have misled SDK consumers.
- Regenerated docs/swagger/{docs.go, swagger.json, swagger.yaml} via
make generate-docs.
Grupo B — Test improvements (3 findings):
- actor_mapping_immutability_fuzz_test.go: replace uuid.NewString() with
a fixed UUID constant fuzzFixedActorID. Random UUIDs per fuzz iteration
violate the project rule of deterministic test data and would make any
fuzz failure non-reproducible.
- actor_mapping_chaos_test.go:482-484: assert.Error/assert.Nil →
require.Error/require.Nil for the graceful-degradation contract
(Upsert with PG unreachable MUST return an error, and MUST NOT also
return a non-nil entity). Subsequent assertions should not run if this
invariant is violated.
- actor_mapping_chaos_test.go:393: assert.Equal → require.Equal for the
zero-plaintext-overwrite security invariant under chaos latency
injection. This is the load-bearing assertion for the entire
pseudonymization-bypass fix; subsequent assertions should fail-fast.
Grupo C — Chaos harness API hygiene (1 nitpick):
- tests/chaos/harness.go: rename ChaosHarness.LockTest →
LockHarnessForTest for clarity (avoids "test the lock" misreading).
- tests/chaos/common.go: add atomic.Bool testLockHeld field on
ChaosHarness. Both LockHarnessForTest and ResetDatabase now
CompareAndSwap before acquiring testMu, failing fast via t.Fatalf if
the harness is already locked by the same test (instead of deadlocking
on double-acquire). All 5 callers in actor_mapping_chaos_test.go
updated to the new name.
Verification:
- go vet ./... clean (including chaos build tag)
- go test -tags=unit ./internal/governance/... all green
- go test -tags=unit ./tests/... all green
- grep display_name in docs/swagger/ → 0 results
- grep LockTest in tests/chaos/ → 0 results
- grep uuid.NewString in fuzz file → 0 results
No production logic changed. Only Swagger doc text, test data sources,
and assertion strictness.
Refs CodeRabbit local review 2026-05-14, 7 findings, all resolved.
* docs(chaos): document serial-execution invariant in harness lock helpers
Addresses CodeRabbit re-review findings #5 and #6 by documenting the
chaos test suite's intentional single-threaded model, rather than
refactoring the testLockHeld CAS-before-mutex pattern.
Background: commit 0e6e076 "test(chaos): serialize actor_mapping chaos
tests..." established that the chaos suite runs with -p 1 (see Makefile
target test-chaos). Under this model, LockHarnessForTest and
ResetDatabase never run concurrently from different tests; the
testLockHeld flag exists only to detect the same-test double-lock
scenario (a test that mistakenly calls both helpers, which would
deadlock on testMu).
The current CAS-before-mutex pattern fails fast via t.Fatalf when the
flag is already set, instead of blocking on the mutex. This is correct
under serial execution and is now explicitly documented as deliberate.
If the chaos suite is ever changed to permit concurrent test execution,
the docstring flags that the CAS pattern must be revisited (the current
pattern would incorrectly fail legitimate concurrent tests instead of
serializing them through proper mutex contention).
Changes:
- tests/chaos/harness.go: append SERIAL-EXECUTION INVARIANT block to
LockHarnessForTest docstring (full rationale + revisit-trigger note)
and a shorter cross-reference paragraph to ResetDatabase docstring.
- No code changes; testLockHeld CAS and testMu logic untouched.
Findings #1, #2, #3, #4 deliberately deferred:
- #1 (state metrics zeroed): metadata, not entrega
- #2/#3 (task spec post-hoc edits): task spec is historical spec
- #4 (reflectKindCheck): conscious decision from Gate 8 iter 1
* docs(governance): include MTCH-0604 in 409 swagger description
Addresses CodeRabbit round-3 finding #1 (minor potential_issue) by
appending the explicit error code MTCH-0604 to the @failure 409
annotation on UpsertActorMapping. The 409 response in swagger.json now
reads "Actor mapping identity is immutable (MTCH-0604)", making the
API contract self-documenting for consumers parsing only the OpenAPI
spec (without needing to inspect ErrorResponse examples).
Files:
- handlers_actor_mapping.go: 1-line annotation update
- docs/swagger/{docs.go,swagger.json,swagger.yaml}: regenerated via
make generate-docs
Other CodeRabbit round-3 findings deliberately skipped:
- #2 (CRITICAL, fuzz build tag): CodeRabbit suggested changing
//go:build unit → //go:build fuzz in actor_mapping_fuzz_test.go. This
conflicts with the Matcher project's local convention: all 23 other
fuzz_test.go files use //go:build unit (verified via grep) and there
is no test-fuzz Makefile target. The suggestion comes from a generic
Ring standard; local convention prevails. Changing the tag would
break fuzz execution under `make test-unit` and create inconsistency
with the rest of the codebase.
- #3 (trivial, reflectKindCheck): repeated nitpick from Gate 8 iter 1
and round 2; conscious decision retained.
- #4 (trivial, task spec isolation level clarification): task spec is
a historical planning document; post-hoc edits skipped per
consistent policy.
* style(governance): fix gci comment indentation on ActorMapping docstring
CI lint failure on Go Analysis / Lint (matcher) job (run 25940398927)
flagged the docstring at actor_mapping.go:63 as "File is not properly
formatted (gci)". Root cause: the Immutability contract list items
(a) UPDATE... / b) DELETE... used 7 spaces of indentation after the
// prefix; golangci-lint's gci/gofumpt enforcement wants 5 spaces to
align with the parent list bullet style.
Reduced indentation from 7 spaces to 5 spaces on both bullets. No
content change — only whitespace inside the comment block.
Local make lint earlier in the cycle had stale cache; running
make lint-fix now reproduces and corrects the issue. Verified
make lint clean post-fix (0 issues).
* build(deps): bump golang from 1.26.2-alpine to 1.26.3-alpine
Cherry-picks the change from open dependabot PR #140 to unblock the
security scan CI on this PR. The 1.26.2-alpine base image carries 16
Go stdlib/runtime CVEs from the 2026 disclosure cycle:
- CVE-2026-33811 (LookupCNAME cgo DNS DoS)
- CVE-2026-33814 (HTTP/2 SETTINGS infinite loop)
- CVE-2026-39820 (ParseAddress/ParseAddressList DoS)
- CVE-2026-39836 (Dial/LookupPort NUL byte panic on Windows)
- CVE-2026-42499 (consumePhrase DoS)
- CVE-2026-39823/25/26 (URL parsing, ReverseProxy, html/template)
All fixed in 1.26.3-alpine. Bump is byte-for-byte identical to PR #140
(automated dependabot upgrade); applied here because the security gate
on PR #150 is otherwise blocking on these pre-existing CVEs that this
PR did not introduce.
If #140 merges into develop first, the resulting merge conflict on this
PR will be trivial (same single-line change).
Scope diluition is justified: the bump is the upstream-recommended fix
for the exact CVEs blocking this PR's CI; combining them in one PR
avoids a circular dependency where neither can merge without the other.
* test(governance): assert timestamps unchanged on idempotent PUT
Applies CodeRabbit Cloud finding C (trivial nitpick, quick win) on
PR #150. The TestActorMapping_IdempotentSamePayload e2e journey now
also asserts that `CreatedAt` and `UpdatedAt` remain byte-identical
between the first and second PUT responses, strengthening the no-op
contract for AC2 (idempotent PUT with identical payload).
Previously the test only verified that identity fields (displayName,
email) round-tripped intact. Adding the timestamp assertions guards
against a regression where the repository would touch updated_at on a
no-op write — e.g. if the INSERT ... ON CONFLICT DO NOTHING path were
ever changed to ON CONFLICT DO UPDATE with COALESCE again.
The integration-tier check already pins this at second precision
(actor_mapping_immutability_integration_test.go); this e2e assertion
adds end-to-end timestamp stability through the full HTTP + API client
stack.
Other CodeRabbit Cloud findings deliberately deferred (see PR replies):
- A (typed input struct for CreateOrGetActorMapping): inconsistent with
sibling commands in the same file that use primitive params; would
require broader cleanup PR
- B (manual stub for ActorMappingRepository): MockActorMappingRepository
is already generated by mockgen and used by sibling tests; refactor
would create divergence
- D (ErrActorMappingImmutable in entity file): sentinel already lives in
domain/errors/errors.go parallel to ErrActorMappingNotFound, with
type-aliases at service and adapter layers; adding a fourth
declaration site duplicates without resolving
* test(governance): assert non-empty timestamps and GET-PUT timestamp parity
Applies CodeRabbit Cloud follow-up nitpick on PR #150 (review at
2026-05-15T21:17:53Z). Extends the timestamp assertions in
TestActorMapping_IdempotentSamePayload with:
1. Non-empty assertions on the first PUT response (createdAt, updatedAt)
to guard against a false-positive where both responses happen to
carry zero-valued timestamps.
2. GET response timestamp parity vs the first PUT response, asserting
that GET preserves the same CreatedAt/UpdatedAt the row was inserted
with — i.e., the read path does not synthesize new timestamps and
the row was never silently rewritten between PUT and GET.
Combined with the existing PUT-vs-PUT timestamp equality (commit
0441fe8), the e2e idempotency journey now pins the full chain:
- First PUT returns non-zero timestamps
- Second PUT echoes the same timestamps (no-op write contract)
- GET returns those same timestamps (read path is faithful)
* docs(task): align task spec file list with actual implementation paths
Addresses CodeRabbit Cloud review 4301505026 — the "Arquivos afetados"
section of the task spec listed paths/symbols speculated during planning
that ended up diverging from the implementation:
- ErrActorMappingImmutable moved from services/command/commands.go to
domain/errors/errors.go (matches existing governance error pattern;
re-exported via type-aliases at service and adapter layers)
- IdentityEquals helper was not added to the entity; comparison logic
lives in the adapter as actorMappingPIIDiffers / stringPtrEqual
- New shared helpers (LogSpanBusinessEvent), constants
(CodeGovernanceActorMappingImmutable), and error catalog entries
(defGovernanceActorMappingImmutable) were not anticipated by the
original task spec but materialized during implementation
- Test file inventory now lists the actual filenames
(*_immutable_test.go, *_immutability_*_test.go) instead of the original
speculative names
The task spec now serves as an accurate map of the implementation for
future maintainers reading docs/tasks/.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## [3.0.0-beta.1](v2.1.1...v3.0.0-beta.1) (2026-05-15) ### ⚠ BREAKING CHANGES * **governance:** footer in any branch commit, so semver may emit only a patch bump for a public-API breaking change) is surfaced for the release owner as a follow-up; it is out of Gate 8 cleanup scope. Refs Gate 8 review (ring:codereview iteration 1). * chore(dev-cycle): commit cycle artifacts for fix/governance-actor-mapping-pseudonymization-bypass Persists the dev-cycle state file and task spec as audit artifacts for the actor_mapping pseudonymization bypass fix. Cycle summary: - Source: docs/tasks/fix-actor-mapping-pseudonymization-bypass.md - Origin: Pentest Taura Security 28/04/2026 - Task: T-001 (1 subtask: ST-001-01) — completed - Total commits in branch: 17 (16 + this artifact commit) - Gates closed (lean backend flow): * Gate 0 (Implementation): TDD-RED 430e81b, TDD-GREEN 4f595b1, plus fuzz/property/integration/chaos/e2e/observability/migration work consolidated under the lean flow's Gate 0 quality umbrella * Gate 8 (Codereview): 10/10 reviewers PASS, iteration 1, 4 MEDIUMs resolved (M-1/M-2/M-3 fixed in commit 2cbee71, M-4 deferred to release engineering) * Gate 9 (Validation): user APPROVED, all 10 ACs verified * Gate 0.5D (Migration Safety): PASS — migration 000033 is documentation-only (COMMENT ON TABLE), zero schema mutation, fully reversible State file is preserved as the cycle audit record. Refs: /ring:dev-cycle resume session 2026-05-14. * chore(dev-cycle): mark cycle as completed Final cycle close for fix-actor-mapping-pseudonymization-bypass-2026-05-13. - status: in_progress → completed - feedback_loop_completed: false → true - task T-001: in_progress → completed - completed_at: 2026-05-14T15:55:00Z ring:dev-report dispatch deferred for context economy; can be re-run via /ring:dev-report when continuous-improvement metrics are desired. All gates closed (lean backend flow): - Gate 0 (Implementation): ✓ - Gate 8 (Codereview, 10/10 PASS): ✓ - Gate 9 (Validation, user APPROVED): ✓ - Gate 0.5D (Migration safety): ✓ * chore(governance): apply CodeRabbit local review findings Applies all 7 findings from the local CodeRabbit review against the fix-actor-mapping-pseudonymization-bypass branch before opening PR. Grupo A — Swagger field name (3 findings, 1 root cause): - handlers_actor_mapping.go: replace display_name with displayName in the Swagger @description and doc comment for UpsertActorMapping. The request JSON field is camelCase per the DTO, so the snake_case description would have misled SDK consumers. - Regenerated docs/swagger/{docs.go, swagger.json, swagger.yaml} via make generate-docs. Grupo B — Test improvements (3 findings): - actor_mapping_immutability_fuzz_test.go: replace uuid.NewString() with a fixed UUID constant fuzzFixedActorID. Random UUIDs per fuzz iteration violate the project rule of deterministic test data and would make any fuzz failure non-reproducible. - actor_mapping_chaos_test.go:482-484: assert.Error/assert.Nil → require.Error/require.Nil for the graceful-degradation contract (Upsert with PG unreachable MUST return an error, and MUST NOT also return a non-nil entity). Subsequent assertions should not run if this invariant is violated. - actor_mapping_chaos_test.go:393: assert.Equal → require.Equal for the zero-plaintext-overwrite security invariant under chaos latency injection. This is the load-bearing assertion for the entire pseudonymization-bypass fix; subsequent assertions should fail-fast. Grupo C — Chaos harness API hygiene (1 nitpick): - tests/chaos/harness.go: rename ChaosHarness.LockTest → LockHarnessForTest for clarity (avoids "test the lock" misreading). - tests/chaos/common.go: add atomic.Bool testLockHeld field on ChaosHarness. Both LockHarnessForTest and ResetDatabase now CompareAndSwap before acquiring testMu, failing fast via t.Fatalf if the harness is already locked by the same test (instead of deadlocking on double-acquire). All 5 callers in actor_mapping_chaos_test.go updated to the new name. Verification: - go vet ./... clean (including chaos build tag) - go test -tags=unit ./internal/governance/... all green - go test -tags=unit ./tests/... all green - grep display_name in docs/swagger/ → 0 results - grep LockTest in tests/chaos/ → 0 results - grep uuid.NewString in fuzz file → 0 results No production logic changed. Only Swagger doc text, test data sources, and assertion strictness. Refs CodeRabbit local review 2026-05-14, 7 findings, all resolved. * docs(chaos): document serial-execution invariant in harness lock helpers ### Bug Fixes * **governance:** close actor_mapping pseudonymization bypass ([#150](#150)) ([afed31d](afed31d)), closes [#5](#5) [#6](#6) [#1](#1) [#2](#2) [#3](#3) [#4](#4) [#1](#1) [#2](#2) [#3](#3) [#4](#4) [#1](#1) [#2](#2) [#3](#3) [#4](#4) [#140](#140) [#140](#140) [#140](#140)
Addresses 6 actionable findings from the CodeRabbit Cloud review of the re-submitted security fix. All are quality refinements on artifacts we authored; no behavior change to the security contract itself. Code fixes: - fuzz test buildActorMapping (#5): validate UTF-8 only on fields the caller marks as present. The previous guard rejected the entire mapping when an absent field happened to carry invalid bytes — those bytes are never read in the absent branch, so the rejection only shrank the valid input space without protecting any assertion. - integration test idempotency assertions (#6): switch from .Unix() epoch-seconds comparison to time.Time.Equal(). Sub-second drift was previously absorbed by the seconds-precision rounding; the tighter comparison now surfaces any spurious updated_at write introduced by a future regression. Applied at both call sites in the AC2 and AC8-identical-payload tests. - chaos harness fatal message (#10): the t.Fatalf text on the testLockHeld CAS used to say "called twice on the same test", but the CAS is harness-scoped, so any second acquirer (including a future parallel test if the suite is ever de-serialized) would land in the same branch. Rephrase the message to reference the chaos suite serial-execution invariant and the docstring that explains it. Applied to both ResetDatabase and LockHarnessForTest. Documentation: - ActorMappingRepository.Upsert contract (#7): the docstring said identity fields must match "exactly", but the adapter helpers (stringPtrEqual / actorMappingPIIDiffers) intentionally treat nil-pointer and empty-string as equivalent because the DB stores NULL for both. Document the equivalence explicitly in the contract so future maintainers don't read "exactly" as byte-strict including nil-vs-empty. - Task spec PoC step 1 (#4): the pentest reproduction in docs/tasks/fix-actor-mapping-pseudonymization-bypass.md said "POST /v1/governance/actor-mappings/{ID} creates mapping". The actual route is PUT — there is no POST create endpoint. Corrected with a clarifying parenthetical. - Cycle state metrics (#1): docs/ring:dev-cycle/current-cycle.json had accumulated_metrics.review_iterations: 0 despite the cycle documenting Gate 8 iteration 1 plus 4 MEDIUM findings resolved. Updated to review_iterations: 1 and populated issues_by_severity with the actual counts (4 MEDIUM, 22 LOW) so the state file truthfully audits the cycle. Findings #2, #3, #8, #9 are tracked as deferred with replies on the PR threads — they cover policy decisions (pre-launch patch posture), process documentation that was already conscious, sibling-method consistency, and an intentional defensive check.
Bumps LerianStudio/github-actions-shared-workflows/.github/workflows/pr-validation.yml from 1.10.2 to 1.11.0.
Commits
341f65fMerge pull request #80 from LerianStudio/feature/pr-analysis-changes23e9977fix(go-pr-analysis): use .ignorecoverunit for report filtering only7c8fe0dfix(go-pr-analysis): exclude .ignorecoverunit folders from testing1d2d27efix(go-pr-analysis): match Midaz coverage-unit package filtering576caf4fix(go-pr-analysis): filter packages with .ignorecoverunit before running tests3fcc29ffix(go-pr-analysis): always generate SARIF with gosec action0182ab7fix(go-pr-analysis): install golangci-lint at start of lint jobbe00205fix(go-pr-analysis): only use make lint if golangci-lint is installed950b622fix(go-pr-analysis): check .ignorecoverunit in repo root, not just working dir81cfb35fix(go-pr-analysis): support cover-html target and always use Makefile when a...Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)