Skip to content

bug(audit): AuditEntry has duplicate field declarations; container_runtime vs compute_driver name mismatch #2474

@sunilp

Description

@sunilp

Summary

AuditEntry in agent-governance-python/agent-mesh/src/agentmesh/governance/audit.py
declares sandbox_id, environment, and container_runtime twice in the
class body. Pydantic v2 keeps the second declaration. One of the second
declarations uses a different name (compute_driver vs container_runtime),
so the surviving field set drifts from the §4.3 spec and from what
AuditLog.log() populates.

Net effect: entries built via AuditLog.log() have container_runtime set
and compute_driver left empty; entries built directly via AuditEntry(...)
have compute_driver auto-populated from env and container_runtime left
empty. The same physical concept ends up in different fields depending on
the construction path.

Repro

agent-governance-python/agent-mesh/src/agentmesh/governance/audit.py
lines 97-112 (post-#2473 merge: same offsets, the PR does not touch this block):

    # Execution-context enrichment (optional; not included in integrity hash)
    sandbox_id: Optional[str] = None            # ← first declaration
    environment: Optional[str] = None           # ← first declaration
    container_runtime: Optional[str] = None     # ← first declaration (NEVER overwritten)
    # Sandbox/environment context (auto-populated from env vars when available)
    sandbox_id: Optional[str] = Field(          # ← second declaration; this wins
        default=None,
        description="Sandbox or container ID. Reads SANDBOX_ID or OPENSHELL_SANDBOX_ID env var.",
    )
    environment: Optional[str] = Field(         # ← second declaration; this wins
        default=None,
        description="Deployment environment. Reads AGT_ENVIRONMENT env var.",
    )
    compute_driver: Optional[str] = Field(      # ← NOTE: different name from line 99
        default=None,
        description="Compute driver (e.g., docker, openshell, aca). Reads OPENSHELL_COMPUTE_DRIVER env var.",
    )

AuditLog.log() at line ~454 (post-#2473: line offsets shift slightly):

entry = AuditEntry(
    ...
    sandbox_id=self._env_context.sandbox_id,
    environment=self._env_context.environment,
    container_runtime=self._env_context.container_runtime,  # ← populates the leftover first-decl field
    ...
)

model_post_init() at line ~118 only auto-populates compute_driver,
never container_runtime:

if self.compute_driver is None:
    self.compute_driver = os.environ.get("OPENSHELL_COMPUTE_DRIVER") or None

Expected behavior

Per spec docs/specs/AUDIT-COMPLIANCE-1.0.md §4.3, the field is compute_driver
and the auto-population source is OPENSHELL_COMPUTE_DRIVER (§4.5). The
implementation should have a single compute_driver field consistently
populated by both AuditLog.log() and model_post_init().

Actual behavior

Two fields exist on the model (container_runtime from the leftover first
declaration, compute_driver from the surviving second declaration). Different
construction paths populate different fields.

Suggested fix (out of scope for this issue)

  1. Remove the redundant first declaration block (lines 97-99).
  2. Rename AuditLog.log()'s container_runtime=... kwarg and the
    _EnvContext.container_runtime attribute to compute_driver to match
    the spec and the surviving field.
  3. Decide on one env-var source. The spec table says OPENSHELL_COMPUTE_DRIVER
    (§4.5); _capture_env_context() reads OPENSHELL_CONTAINER_RUNTIME;
    model_post_init() reads OPENSHELL_COMPUTE_DRIVER. These need to agree.

Discovered via

External conformance review against the AgentBoundary v0.1 receipt spec — see
#2449 and PR #2473.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-review:HIGHContributor reputation check flagged HIGH risk

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions