Skip to content

SPEC-029 Amendment 1: refuse a request without an actions assertion - #204

Merged
Maurice1969DB merged 2 commits into
mainfrom
spec-029-am1
Nov 2, 2026
Merged

Maurice1969DB merged 2 commits into
mainfrom
spec-029-am1

Conversation

@Maurice1969DB

Copy link
Copy Markdown
Contributor

What

POST /v1/sign now refuses a request that carries no actions assertion. That covers a body without extra_assertions, an empty array, and an array with no c2pa.actions assertion. The answer is 400 with an actions assertion (c2pa.actions.v2) is required, the audit records rejected, and nothing is signed. The spec text is SPEC-029 Amendment 1, approved 2026-11-02, with a one-line pointer from SPEC-011's resolved question. That resolution about the assertion's contents stands.

Why

  • c2pa-rs 0.91 refuses such a manifest after signing (verify-after-sign, c2pa-rs #2277). The service then answers 500 through its catch path, measured on c2pa-node 0.9.10 (NOTES Step 74). On today's engine, 0.90.22, the same request is signed into a manifest every verifier reads as Invalid. Neither outcome is useful. This check is independent of the engine, so it can ship before the bump.
  • It closes a gap in REQUIRE_AI_MARKING. With the policy on, a body without the extra_assertions key was signed with no AI marking at all. rejectAssertions() returned early when the key was absent, before the policy check. An empty array was refused correctly. Measured 2026-11-02, reachable only with the service token.

Who notices

  • ManifestBuilder users: nobody. The builder always emits exactly one actions assertion.
  • A hand-built new Manifest($type, []): it now gets a SigningFailedException instead of an Invalid manifest. Nothing in the repository builds one.
  • Direct callers of the service that send no actions assertion.

Tests

  • AC10/AC11, in ActionsStructureTest, three datasets. They assert the error text, the audit outcome and the audit reason. Seen red on the pre-amendment service: 200 in all three.
  • AC12, two datasets, running only under REQUIRE_AI_MARKING=true (the hardened profile). Seen red before the fix: without the key, 200; with [], the policy reason.
  • The old "still signs a request carrying no actions assertion at all" test is replaced. UnauthenticatedBoundsTest's spec030Post() now sends an actions assertion.

Verified locally

  • Integration group with default settings: 219 passed / 25 skipped. It was 217 / 23 before; the new and removed tests account for the difference exactly.
  • Integration group with REQUIRE_AI_MARKING=true: 220 passed / 24 skipped.
  • --group=SPEC-030 with the auth-limited settings: 11 passed / 4 skipped.
  • bin/e2e.php: trusted, Article 50 mark intact.
  • composer check: 528 passed / 7 skipped.
  • bin/spec-check.php: 0 errors.

Delivery

The behaviour is in service/, so it arrives through git pull and a rebuild, not through a tag. The docs (docs/service.md, primer §3) are in docs/, so they ship with the next tag. The CHANGELOG says both.

…ertion

c2pa-rs 0.91 verifies after signing and refuses a claim-v2 manifest with
no actions assertion, so the service answers 500 where SPEC-029 AC6
expected a signature (measured on c2pa-node 0.9.10, NOTES Step 74). The
amendment makes the service refuse such a request itself, with a 400 and
a named reason, on every engine. SPEC-011's "not required" about the
contents of the actions assertion stays as it is.

Found while writing it, measured on the current service: with
REQUIRE_AI_MARKING=true, a body without the extra_assertions key is
signed (200), because rejectAssertions() returns before the policy check
when the key is absent. AC12 pins both forms.

Draft: no code, no tests yet.
Amendment 1 approved 2026-11-02. rejectAssertions() treats an absent
extra_assertions key as an empty array and refuses when no c2pa.actions
assertion is present, with "an actions assertion (c2pa.actions.v2) is
required", before the REQUIRE_AI_MARKING check.

This also closes a policy gap: with REQUIRE_AI_MARKING=true a body
without the key returned early and was signed with no AI marking.

Tests first, seen red on the pre-amendment service: AC10 (three
datasets, 200 each) and AC12 under REQUIRE_AI_MARKING (no key: 200;
[]: the policy reason). The old "still signs" test is replaced, and
spec030Post() now sends an actions assertion.

Verified locally: integration 219 passed / 25 skipped (defaults),
220 / 24 (REQUIRE_AI_MARKING=true), SPEC-030 in the auth-limited
settings 11 / 4, bin/e2e.php trusted with the Article 50 mark,
composer check 528 / 7.
@Maurice1969DB
Maurice1969DB merged commit 8cbcdc6 into main Nov 2, 2026
20 checks passed
@Maurice1969DB
Maurice1969DB deleted the spec-029-am1 branch November 2, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant