apiVersion: intentspec.io/v1alpha1
kind: IntentSpec
metadata:
  id: b0a1b6b6-62d1-4c8e-9b8d-1ef5a7b8d7b1
  createdAt: '2026-02-19T11:00:00Z'
  createdBy:
    type: user
    id: bob
    displayName: Bob Li
  target:
    repo:
      type: git
      locator: git@company.internal:data/report-api.git
    baseRef: main
    workspaceId: ws-report-v2
    labels:
      ticket: REPORT-891
      epic: export-v2
      team: data-platform
intent:
  summary: Add field-allowlist filter capability to the /v2/report export endpoint
  problemStatement: 'The current GET /v2/report export endpoint returns all fields, causing large report requests to exceed
    50 MB bandwidth and 30 seconds processing time. We need to add an optional `fields` query parameter supporting a comma-separated
    field allowlist, while maintaining backwards compatibility (omitting fields returns all fields). Related JIRA epic: REPORT-800.'
  changeType: feature
  objectives:
  - Add optional `fields` query parameter to GET /v2/report accepting a comma-separated field allowlist
  - 'Backend filtering logic: return only listed fields; return all fields when the parameter is absent'
  - Update OpenAPI documentation (openapi.yaml) with the new `fields` parameter description
  - Add contract tests covering normal paths and edge cases for both with and without the `fields` parameter
  inScope:
  - Handler and filter logic under src/report/
  - Parameter definition for /v2/report in openapi.yaml
  - Contract tests under tests/contract/
  outOfScope:
  - Do not modify the authorisation model (existing permission checks unchanged)
  - Do not introduce external data sources (no new DB tables or external API calls)
  - Do not change the response structure (existing field semantics and types unchanged)
  touchHints:
    files:
    - src/report/handler.py
    - src/report/filter.py
    - openapi.yaml
    - tests/contract/test_report_v2.py
    symbols:
    - get_report
    - apply_field_filter
    - ReportHandler
    apis:
    - /v2/report
acceptance:
  successCriteria:
  - Response body contains only name and date when called with fields=name,date
  - Response body is identical to current behaviour when fields parameter is absent (backwards compatible)
  - HTTP 400 with error code ERR_INVALID_FIELD returned when fields contains a non-existent field name
  - All contract tests pass
  - No High or above severity findings from SAST/SCA
  - SBOM generated and all licences comply with the allowlist
  verificationPlan:
    fastChecks:
    - id: unit
      kind: command
      command: pytest -q tests/unit/test_report_filter.py
      timeoutSeconds: 300
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - test-log
    - id: mypy
      kind: command
      command: mypy src/report/ --ignore-missing-imports
      timeoutSeconds: 120
      expectedExitCode: 0
      required: true
      artifactsProduced: []
    integrationChecks:
    - id: contract
      kind: command
      command: pytest -q tests/contract/test_report_v2.py -v --tb=short
      timeoutSeconds: 1800
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - test-log
    - id: openapi-lint
      kind: command
      command: spectral lint openapi.yaml --ruleset .spectral.yaml
      timeoutSeconds: 60
      expectedExitCode: 0
      required: true
      artifactsProduced: []
    securityChecks:
    - id: sast
      kind: policy
      command: semgrep --config auto src/report/ --sarif --output reports/sast-report.sarif
      timeoutSeconds: 900
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - sast-report
    - id: sca
      kind: policy
      command: pip-audit --format json --output reports/sca-report.json && cyclonedx-py -o reports/sbom.json
      timeoutSeconds: 600
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - sca-report
      - sbom
    releaseChecks:
    - id: changelog
      kind: policy
      command: changelog-check --require-entry --version-from pyproject.toml
      timeoutSeconds: 30
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - release-notes
    - id: human-approval
      kind: policy
      command: require-approvers --min 1 --group data-platform-reviewers
      timeoutSeconds: 86400
      expectedExitCode: 0
      required: true
      artifactsProduced: []
    - id: provenance-attest
      kind: policy
      command: generate-attestation --intentspec-digest $INTENTSPEC_DIGEST --output reports/provenance.json
      timeoutSeconds: 120
      expectedExitCode: 0
      required: true
      artifactsProduced:
      - provenance-attestation
constraints:
  security:
    networkPolicy: deny
    dependencyPolicy: allow-with-review
    cryptoPolicy: ''
  privacy:
    dataClassesAllowed:
    - public
    - internal
    redactionRequired: true
    retentionDays: 30
  licensing:
    allowedSpdx:
    - Apache-2.0
    - MIT
    - BSD-3-Clause
    - ISC
    forbidNewLicenses: true
  platform:
    languageRuntime: python3.11
    supportedOS:
    - linux
  resources:
    maxWallClockSeconds: 14400
    maxCostUnits: 500
risk:
  level: medium
  rationale: Adds a new API query parameter and backend filter path involving changes to multiple files. Contract tests are
    required to verify backwards compatibility. New dependency (filter library) requires SCA review. No authentication/authorisation
    changes; impact is bounded.
  factors:
  - new-api-param
  - multi-file
  - new-dependency-possible
  - data-path
  humanInLoop:
    required: true
    minApprovers: 1
evidence:
  strategy: pinned-official
  trustTiers:
  - repo
  - standards
  - vendor-doc
  domainAllowlistMode: allowlist-only
  allowedDomains:
  - docs.python.org
  - fastapi.tiangolo.com
  - docs.pydantic.dev
  - nvlpubs.nist.gov
  - slsa.dev
  blockedDomains: []
  minCitationsPerDecision: 2
security:
  toolAcl:
    allow:
    - tool: workspace.fs
      actions:
      - read
      - write
      constraints:
        writeRoots:
        - ./src/report
        - ./tests/contract
        - ./openapi.yaml
        - ./reports
        maxWriteBytes: 5242880
    - tool: workspace.command
      actions:
      - execute
      constraints:
        allowCommands:
        - pytest
        - mypy
        - semgrep
        - pip-audit
        - cyclonedx-py
        - spectral lint
        - changelog-check
        - require-approvers
        - generate-attestation
        maxOutputBytes: 10485760
    - tool: workspace.search
      actions:
      - search
      constraints: {}
    - tool: workspace.lsp
      actions:
      - hover
      - goto-definition
      - find-references
      constraints: {}
    deny:
    - tool: workspace.command
      actions:
      - execute
      constraints:
        denySubstrings:
        - 'curl '
        - 'wget '
        - 'pip install '
        - apt-get
        - sudo
  secrets:
    policy: deny-all
    allowedScopes: []
  promptInjection:
    treatRetrievedContentAsUntrusted: true
    enforceOutputSchema: true
    disallowInstructionFromEvidence: true
  outputHandling:
    encodingPolicy: contextual-escape
    noDirectEval: true
execution:
  retry:
    maxRetries: 3
    backoffSeconds: 15
  replan:
    triggers:
    - repeated-test-fail
    - security-gate-fail
    - evidence-conflict
    - scope-creep
  concurrency:
    maxParallelTasks: 4
artifacts:
  required:
  - name: patchset
    stage: per-task
    required: true
    format: git-diff
  - name: test-log
    stage: integration
    required: true
    format: junit+xml
  - name: sast-report
    stage: security
    required: true
    format: sarif
  - name: sca-report
    stage: security
    required: true
    format: json
  - name: sbom
    stage: security
    required: true
    format: cyclonedx-json
  - name: release-notes
    stage: release
    required: true
    format: markdown
  - name: provenance-attestation
    stage: release
    required: true
    format: in-toto+json
  retention:
    days: 180
provenance:
  requireSlsaProvenance: true
  requireSbom: true
  transparencyLog:
    mode: rekor
  bindings:
    embedIntentSpecDigest: true
    embedEvidenceDigests: true
lifecycle:
  schemaVersion: 1.0.0
  status: active
  changeLog: []
libra:
  objectStore:
    backend: git-native
    blobRetentionStrategy: ref-anchoring
    aiRefPrefix: refs/ai/
  contextPipeline:
    maxFrames: 64
    seedFrameKind: IntentAnalysis
    checkpointOnReplan: true
  planGeneration:
    decompositionMode: per-objective
    conflictResolution: force-serial
    gateTaskPerStage: true
  runPolicy:
    patchsetFormat: GitDiff
    snapshotOnRunStart: true
    metricsSchema:
      wall_clock_seconds:
        type: integer
      cost_usd:
        type: number
      tokens_used:
        type: integer
      patchsets_generated:
        type: integer
  actorMapping:
    orchestratorActorId: libra-orchestrator
    coderActorId: libra-coder
    reviewerActorId: libra-reviewer
  decisionPolicy:
    abandonOnSecurityGateFail: true
    checkpointBeforeReplan: true
    rollbackOnProvenanceFail: true
extensions:
  data-platform.io/slo-impact: medium
  data-platform.io/runbook: https://wiki.company.internal/report-api/runbook
