Skip to content

No end-to-end coverage that the job worker establishes the dispatched-operation carrier #2298

Description

@dawsontoth

The gap

server/jobs/jobProcess.ts establishes the dispatched API operation on async context (runWithDispatchedOperation) before invoking a job's handler. That carrier is what makes an export job's nested SQL scope-checked as export_local rather than as the inner sql — see the DESIGN.md section "The dispatched API operation is carried on async context, never on the request".

Nothing tests that jobProcess.ts actually establishes it. The unit tests in unitTests/security/tokenOperationScope.test.js call runWithDispatchedOperation themselves, so they pin the carrier's contract but would stay green if the jobProcess.ts call were deleted — at which point every export_local-scoped credential would start being refused on its own export, silently as far as CI is concerned.

Why it wasn't covered

The carrier is only observable through tokenScopeDenial, which is inert unless the principal carries tokenOperations. That property has exactly one origin: an OIDC trust-policy exchange (security/authn/oidc/tokenExchange.ts, #2174). Specifically:

  • A scoped token (create_authentication_tokens with an inline role object) is always minted super_user: false (security/tokenAuthentication.ts), and export_local is requires_su — so that route can never reach an export at all.
  • The reachable production shape is an OIDC-exchanged token for a real super_user whose trust policy sets operations.

There is no OIDC integration-test harness — OIDC is unit-tested only (unitTests/security/authn/oidc/) — and standing one up needs a live JWKS issuer.

Also uncovered in the same function, for the same reason

server/jobs/jobProcess.ts deletes a persisted parsed_sql_object (both the top-level and the
nested search_operation position) when it loads the row, so a job queued before the dispatch-time
strip existed — or a row written directly into system.hdb_job — cannot execute an AST carrying
permissions_checked: true that no check ever saw. That line has no direct test either, and for the
same reason: jobProcess.ts is a top-level worker IIFE keyed off process.env, so it is not
reachable in isolation. Its dispatch-time twin is covered, by
unitTests/server/serverHelpers/serverUtilities.test.js's discards a body-supplied parsed_sql_object on the nested search_operation.

So whatever makes jobProcess.ts testable closes two untested branches in one function, not one.

What would close it

Either an OIDC integration harness (reusable well beyond this), or a narrower seam test that drives jobProcess.ts's handler invocation directly and asserts the carrier is in scope.

Found while making processAST honor the permission denial it computes (#2202).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    P3

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions