[GH-ISSUE #5988] [Bug] Managed Evidence identity mismatches return invalid_request #3656

Closed
opened 2026-10-31 00:42:46 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 21, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5988

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

project-managed-application-graph rejects authenticated managed inspection Evidence with contradictory internal identities, but returns invalid_request / invalid_input and recovery.kind: "inspect_input_contract". Its remediation tells the caller to read the input schema and correct listed fields. The request passes the declared schema, and its Evidence semantic ID authenticates; the failure is the disagreement between identities inside that record.

The built CLI reproduced this for three independent cases: subject SHA-256 versus normalized artifact SHA-256, token-scope SHA-256 versus normalized artifact SHA-256, and token-scope MVID versus module MVID. Each returned exit status 1 and the input-contract recovery. The unchanged control returned graph Evidence with exit status 0.

Rejection still works, and the detailed issue message retains the conflicting values. This report concerns the public error classification and recovery advice.

Reproduction

From the built checkout at the revision below, with locked dependencies installed, save the following as reproduce.mjs, then run node --input-type=module < reproduce.mjs from the repository root.

The script uses the production managed graph contract example and Evidence constructor. It deliberately constructs inconsistent records with correctly recomputed semantic IDs, authenticates their serialized forms, validates each request, and invokes the actual CLI. These are synthetic inputs; no managed assembly or native provider executes. All four cases and assertions completed successfully in the reported run.

import assert from 'node:assert/strict';
import { spawnSync } from 'node:child_process';
import { MANAGED_APPLICATION_GRAPH_EXAMPLE } from './dist/contracts/managed/managedWorkflowExamples.js';
import { createEvidence, parseEvidence } from './dist/domain/evidence.js';
import { projectManagedApplicationGraphInputSchema } from './dist/domain/managed/managedApplicationGraph.js';
const original = MANAGED_APPLICATION_GRAPH_EXAMPLE.managed_members;
const base = original.normalized_result;
for (const variant of ['control', 'subject-sha256', 'scope-sha256', 'scope-mvid']) {
  const result = structuredClone(base);
  if (variant === 'scope-sha256') result.identity_scope.requires_artifact_sha256 = 'b'.repeat(64);
  if (variant === 'scope-mvid') result.identity_scope.requires_mvid = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
  const subject = variant === 'subject-sha256'
    ? { path: base.artifact.path, format: 'pe', sha256: 'b'.repeat(64) }
    : undefined;
  const evidence = createEvidence(subject, original.provider, {
    operation: original.operation, parameters: {}, result, rawResult: null,
    limitations: result.limitations,
  });
  parseEvidence(JSON.parse(JSON.stringify(evidence)));
  const input = { managed_members: evidence };
  assert.equal(projectManagedApplicationGraphInputSchema.safeParse(input).success, true);
  const run = spawnSync(process.execPath, ['scripts/rea.mjs', 'project-managed-application-graph', JSON.stringify(input), '--json'], { encoding: 'utf8', timeout: 30000 });
  if (run.error) throw run.error;
  const output = JSON.parse(run.stdout);
  if (variant === 'control') {
    assert.equal(run.status, 0, run.stderr);
    assert.equal(output.operation, 'project_managed_application_graph');
    console.log(JSON.stringify({ variant, exit: run.status, operation: output.operation, summary: output.normalized_result.summary }));
  } else {
    assert.equal(run.status, 1, run.stderr);
    assert.equal(output.code, 'invalid_request');
    assert.equal(output.category, 'invalid_input');
    assert.equal(output.retryable, false);
    assert.deepEqual(output.details.issues[0].path, []);
    assert.equal(output.recovery.kind, 'inspect_input_contract');
    console.log(JSON.stringify({ variant, exit: run.status, output }));
  }
}

Expected behavior

Preserve rejection, but return the existing Evidence-integrity outcome for an internal identity contradiction: evidence_integrity_mismatch / integrity_mismatch, with recovery directed at recreating or obtaining consistent Evidence. Reading a stale request schema cannot repair the relationship between the record's identities.

The managed Evidence contract explicitly requires authentication and a subject/artifact digest cross-check, and says a valid Evidence ID alone does not establish their agreement. EvidenceIntegrityError covers failed Evidence identity checks. Its existing code mapping, category mapping, and recovery message supply those semantics.

Impact and scope

P2: consumers that branch on the public code/category or recovery kind receive a schema-correction action for an Evidence identity failure. The observed mismatch explanation remains available in details.issues[0].message, so a caller can inspect it manually and obtain consistent Evidence. The unchanged control demonstrates that consistent records remain usable.

Runtime scope demonstrated here is the graph command's managed_members input and the three identity relationships above. The same parser is used for the graph's artifact and native-boundary slots; their exposure is source-derived. The MCP graph handler also calls the shared service after its semantic-ID/operation checks; MCP transport behavior was not executed in this reproduction. Natural occurrence and frequency of inconsistent records are unknown. No successful-result corruption or security-boundary crossing was observed.

REA version

rea-agents 6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v26.12.0. The run used this supported Node 26 runtime rather than the repository's exact Node 24.18.0 pin. Built public CLI; no external analysis engine or .NET runtime was used.

Target and artifact context

Synthetic inspect_managed_members Evidence derived from the advertised application-graph example. The baseline normalized artifact SHA-256 is 64 2 characters, and its module MVID is 11112222-3333-4444-9555-666677778888. The changed cases independently introduce a digest of 64 b characters or MVID ffffffff-ffff-ffff-ffff-ffffffffffff. Each record receives a valid semantic ID. No artifact bytes are opened or executed.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

The executed script observed:

control:        exit 0; project_managed_application_graph; 3 nodes, 2 edges, 1 module, 1 method
subject-sha256: exit 1; invalid_request / invalid_input; inspect_input_contract
scope-sha256:   exit 1; invalid_request / invalid_input; inspect_input_contract
scope-mvid:     exit 1; invalid_request / invalid_input; inspect_input_contract

Each failure has retryable: false and an issue with path: [], reason: "invalid_value". The scope-digest failure retains this diagnostic, with its Evidence ID omitted here for readability:

Managed Evidence inspect_managed_members (...) token scope SHA-256 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb does not match normalized artifact SHA-256 2222222222222222222222222222222222222222222222222222222222222222

All three receive the same remediation:

Read the declared input schema or CLI usage for project_managed_application_graph; if using MCP and the catalog may be stale, call tools/list. Correct the listed fields, then retry. Do not repeat the unchanged call.

Typed outcome or recovery expected

Return evidence_integrity_mismatch / integrity_mismatch, retain the Evidence ID and conflicting identity values, and direct the caller to recreate or obtain internally consistent Evidence. Keep retryable: false and preserve rejection. Do not report inspect_input_contract recovery for these identity contradictions. The unchanged control must continue to succeed.

Analysis or suspected cause

Source-derived: parseManagedInspectionEvidence throws TypeError for all three cross-field identity failures. The graph service maps that exception to workflowInputError, which constructs an AnalysisInputError. That selects the request-schema recovery.

A repair needs both a typed identity failure from the owning check and preservation of that failure through the application service: changing only the thrown class would currently route it into the service's generic AnalysisProtocolError branch. Genuine input-shape errors can retain their existing input-error handling. No implementation change was made.

The CLI adapter reaches this shared service directly. The graph domain uses the parser for all three inspection slots.

Additional context

Fetched upstream main 25e1a24a3ed3671a0148757555f18d16c29d936a retains the relevant managed parser, graph service, input helper, and error mappings. Execution used the source revision listed above. No regression range was established.

Related report #5939 concerns a separate NativeAOT snapshot digest producer and Ghidra provider wrapping path; correcting that path does not repair this managed Evidence classification. #5945 concerns snapshot-specific wording after the integrity code is already selected. #3352 concerns an empty module display label; #4639 concerns an MCP operation allowlist. PR #1089 added diagnostic details while explicitly preserving the previous classification; it does not correct this identity-error type.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5988 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `project-managed-application-graph` rejects authenticated managed inspection Evidence with contradictory internal identities, but returns `invalid_request` / `invalid_input` and `recovery.kind: "inspect_input_contract"`. Its remediation tells the caller to read the input schema and correct listed fields. The request passes the declared schema, and its Evidence semantic ID authenticates; the failure is the disagreement between identities inside that record. The built CLI reproduced this for three independent cases: subject SHA-256 versus normalized artifact SHA-256, token-scope SHA-256 versus normalized artifact SHA-256, and token-scope MVID versus module MVID. Each returned exit status 1 and the input-contract recovery. The unchanged control returned graph Evidence with exit status 0. Rejection still works, and the detailed issue message retains the conflicting values. This report concerns the public error classification and recovery advice. ### Reproduction From the built checkout at the revision below, with locked dependencies installed, save the following as `reproduce.mjs`, then run `node --input-type=module < reproduce.mjs` from the repository root. The script uses the production managed graph contract example and Evidence constructor. It deliberately constructs inconsistent records with correctly recomputed semantic IDs, authenticates their serialized forms, validates each request, and invokes the actual CLI. These are synthetic inputs; no managed assembly or native provider executes. All four cases and assertions completed successfully in the reported run. ```js import assert from 'node:assert/strict'; import { spawnSync } from 'node:child_process'; import { MANAGED_APPLICATION_GRAPH_EXAMPLE } from './dist/contracts/managed/managedWorkflowExamples.js'; import { createEvidence, parseEvidence } from './dist/domain/evidence.js'; import { projectManagedApplicationGraphInputSchema } from './dist/domain/managed/managedApplicationGraph.js'; const original = MANAGED_APPLICATION_GRAPH_EXAMPLE.managed_members; const base = original.normalized_result; for (const variant of ['control', 'subject-sha256', 'scope-sha256', 'scope-mvid']) { const result = structuredClone(base); if (variant === 'scope-sha256') result.identity_scope.requires_artifact_sha256 = 'b'.repeat(64); if (variant === 'scope-mvid') result.identity_scope.requires_mvid = 'ffffffff-ffff-ffff-ffff-ffffffffffff'; const subject = variant === 'subject-sha256' ? { path: base.artifact.path, format: 'pe', sha256: 'b'.repeat(64) } : undefined; const evidence = createEvidence(subject, original.provider, { operation: original.operation, parameters: {}, result, rawResult: null, limitations: result.limitations, }); parseEvidence(JSON.parse(JSON.stringify(evidence))); const input = { managed_members: evidence }; assert.equal(projectManagedApplicationGraphInputSchema.safeParse(input).success, true); const run = spawnSync(process.execPath, ['scripts/rea.mjs', 'project-managed-application-graph', JSON.stringify(input), '--json'], { encoding: 'utf8', timeout: 30000 }); if (run.error) throw run.error; const output = JSON.parse(run.stdout); if (variant === 'control') { assert.equal(run.status, 0, run.stderr); assert.equal(output.operation, 'project_managed_application_graph'); console.log(JSON.stringify({ variant, exit: run.status, operation: output.operation, summary: output.normalized_result.summary })); } else { assert.equal(run.status, 1, run.stderr); assert.equal(output.code, 'invalid_request'); assert.equal(output.category, 'invalid_input'); assert.equal(output.retryable, false); assert.deepEqual(output.details.issues[0].path, []); assert.equal(output.recovery.kind, 'inspect_input_contract'); console.log(JSON.stringify({ variant, exit: run.status, output })); } } ``` ### Expected behavior Preserve rejection, but return the existing Evidence-integrity outcome for an internal identity contradiction: `evidence_integrity_mismatch` / `integrity_mismatch`, with recovery directed at recreating or obtaining consistent Evidence. Reading a stale request schema cannot repair the relationship between the record's identities. The [managed Evidence contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/managed-code-analysis.md#L388-L394) explicitly requires authentication and a subject/artifact digest cross-check, and says a valid Evidence ID alone does not establish their agreement. [EvidenceIntegrityError](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/evidenceErrors.ts#L13-L25) covers failed Evidence identity checks. Its existing [code mapping](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorProjection.ts#L250-L260), [category mapping](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorPresentation.ts#L230-L235), and [recovery message](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorPresentation.ts#L269-L274) supply those semantics. ### Impact and scope P2: consumers that branch on the public code/category or recovery kind receive a schema-correction action for an Evidence identity failure. The observed mismatch explanation remains available in `details.issues[0].message`, so a caller can inspect it manually and obtain consistent Evidence. The unchanged control demonstrates that consistent records remain usable. Runtime scope demonstrated here is the graph command's `managed_members` input and the three identity relationships above. The same parser is used for the graph's artifact and native-boundary slots; their exposure is source-derived. The MCP graph handler also calls the shared service after its semantic-ID/operation checks; MCP transport behavior was not executed in this reproduction. Natural occurrence and frequency of inconsistent records are unknown. No successful-result corruption or security-boundary crossing was observed. ### REA version `rea-agents` 6.7.0; source revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v26.12.0. The run used this supported Node 26 runtime rather than the repository's exact Node 24.18.0 pin. Built public CLI; no external analysis engine or .NET runtime was used. ### Target and artifact context Synthetic `inspect_managed_members` Evidence derived from the advertised application-graph example. The baseline normalized artifact SHA-256 is 64 `2` characters, and its module MVID is `11112222-3333-4444-9555-666677778888`. The changed cases independently introduce a digest of 64 `b` characters or MVID `ffffffff-ffff-ffff-ffff-ffffffffffff`. Each record receives a valid semantic ID. No artifact bytes are opened or executed. ### Interface CLI ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence The executed script observed: ```text control: exit 0; project_managed_application_graph; 3 nodes, 2 edges, 1 module, 1 method subject-sha256: exit 1; invalid_request / invalid_input; inspect_input_contract scope-sha256: exit 1; invalid_request / invalid_input; inspect_input_contract scope-mvid: exit 1; invalid_request / invalid_input; inspect_input_contract ``` Each failure has `retryable: false` and an issue with `path: []`, `reason: "invalid_value"`. The scope-digest failure retains this diagnostic, with its Evidence ID omitted here for readability: ```text Managed Evidence inspect_managed_members (...) token scope SHA-256 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb does not match normalized artifact SHA-256 2222222222222222222222222222222222222222222222222222222222222222 ``` All three receive the same remediation: ```text Read the declared input schema or CLI usage for project_managed_application_graph; if using MCP and the catalog may be stale, call tools/list. Correct the listed fields, then retry. Do not repeat the unchanged call. ``` ### Typed outcome or recovery expected Return `evidence_integrity_mismatch` / `integrity_mismatch`, retain the Evidence ID and conflicting identity values, and direct the caller to recreate or obtain internally consistent Evidence. Keep `retryable: false` and preserve rejection. Do not report `inspect_input_contract` recovery for these identity contradictions. The unchanged control must continue to succeed. ### Analysis or suspected cause Source-derived: [parseManagedInspectionEvidence](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/managed/managedInspectionEvidence.ts#L31-L54) throws `TypeError` for all three cross-field identity failures. [The graph service](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/managed/ManagedApplicationGraphService.ts#L31-L45) maps that exception to [workflowInputError](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/workflowInputError.ts#L20-L34), which constructs an `AnalysisInputError`. That selects the request-schema recovery. A repair needs both a typed identity failure from the owning check and preservation of that failure through the application service: changing only the thrown class would currently route it into the service's generic `AnalysisProtocolError` branch. Genuine input-shape errors can retain their existing input-error handling. No implementation change was made. The [CLI adapter](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/cli/managedProjectGraphCommand.ts#L16-L32) reaches this shared service directly. The graph domain [uses the parser for all three inspection slots](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/managed/managedApplicationGraph.ts#L206-L232). ### Additional context Fetched upstream main `25e1a24a3ed3671a0148757555f18d16c29d936a` retains the relevant managed parser, graph service, input helper, and error mappings. Execution used the source revision listed above. No regression range was established. Related report #5939 concerns a separate NativeAOT snapshot digest producer and Ghidra provider wrapping path; correcting that path does not repair this managed Evidence classification. #5945 concerns snapshot-specific wording after the integrity code is already selected. #3352 concerns an empty module display label; #4639 concerns an MCP operation allowlist. PR #1089 added diagnostic details while explicitly preserving the previous classification; it does not correct this identity-error type.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3656
No description provided.