# Zindex - Compliance / PII data-flow diagram. Maintains a regulator-friendly
# diagram of where sensitive data moves between systems. Runs monthly on the
# 1st (audit-cycle cadence) and on every PR that touches the data-classification
# inventory. Designed so the rendered SVG + revision diff become the canonical
# audit-pack evidence.
#
# Drop into .github/workflows/zindex-compliance.yml.

name: Zindex - Compliance PII data-flow

on:
  pull_request:
    paths:
      - "compliance/data-classification.yaml"
      - "compliance/trust-boundaries.yaml"
  schedule:
    - cron: "0 0 1 * *"   # Monthly: 1st of each month, 00:00 UTC
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
  ZINDEX_API_BASE: https://api.zindex.ai

jobs:
  sync-data-flow:
    runs-on: ubuntu-latest
    environment: compliance   # gate: requires reviewer approval if configured
    steps:
      - uses: actions/checkout@v4

      # 1. Read the data-classification inventory + trust-boundary config.
      #    Author scripts/parse-classification.mjs against your compliance
      #    docs convention (typically one YAML file mapping system →
      #    classification + a list of external trust boundaries).
      - name: Parse classification inventory
        run: |
          mkdir -p out
          node scripts/parse-classification.mjs > out/classification.json

      - name: Capture current revision
        id: prev_rev
        env:
          ZINDEX_API_KEY: ${{ secrets.ZINDEX_API_KEY }}
          ZINDEX_SCENE_ID: ${{ secrets.ZINDEX_SCENE_ID }}
        run: |
          echo "rev=$(curl -fsSL -H "Authorization: Bearer $ZINDEX_API_KEY" \
            "$ZINDEX_API_BASE/v1/scenes/$ZINDEX_SCENE_ID" | jq -r '.revision')" >> "$GITHUB_OUTPUT"

      # 2. Compute applyOps batch. Audit-friendly tip: the revisionMessage
      #    becomes the audit log entry - make it descriptive
      #    ("Q3 2026: add tokenization layer between webapp and customer vault").
      - name: Compute applyOps batch
        run: node scripts/classification-to-ops.mjs out/classification.json > out/ops.json

      - name: Apply ops
        id: apply
        env:
          ZINDEX_API_KEY: ${{ secrets.ZINDEX_API_KEY }}
          ZINDEX_SCENE_ID: ${{ secrets.ZINDEX_SCENE_ID }}
        run: |
          RESP=$(curl -fsSL -X POST \
            -H "Authorization: Bearer $ZINDEX_API_KEY" \
            -H "Content-Type: application/json" \
            --data-binary @out/ops.json \
            "$ZINDEX_API_BASE/v1/scenes/$ZINDEX_SCENE_ID/ops")
          echo "rev=$(echo "$RESP" | jq -r '.revision')" >> "$GITHUB_OUTPUT"
          echo "applied=$(echo "$RESP" | jq -r '.applied')" >> "$GITHUB_OUTPUT"

      - name: Render
        env:
          ZINDEX_API_KEY: ${{ secrets.ZINDEX_API_KEY }}
          ZINDEX_SCENE_ID: ${{ secrets.ZINDEX_SCENE_ID }}
        run: |
          curl -fsSL -X POST \
            -H "Authorization: Bearer $ZINDEX_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"format":"svg","theme":"clean"}' \
            "$ZINDEX_API_BASE/v1/scenes/$ZINDEX_SCENE_ID/render" \
            | jq -r '.output.content' > out/diagram.svg

      # 3. Audit-cycle diff: compares current to the revision pinned at the
      #    start of the audit period (stored as the AUDIT_BASELINE_REVISION
      #    secret - update it each new audit cycle). This produces the
      #    "what changed since last audit?" answer.
      - name: Diff against audit baseline
        id: diff
        env:
          ZINDEX_API_KEY: ${{ secrets.ZINDEX_API_KEY }}
          ZINDEX_SCENE_ID: ${{ secrets.ZINDEX_SCENE_ID }}
          BASELINE: ${{ secrets.AUDIT_BASELINE_REVISION }}
          NEW: ${{ steps.apply.outputs.rev }}
        run: |
          curl -fsSL \
            -H "Authorization: Bearer $ZINDEX_API_KEY" \
            "$ZINDEX_API_BASE/v1/scenes/$ZINDEX_SCENE_ID/diff?from=$BASELINE&to=$NEW" \
            > out/audit-diff.json
          echo "added=$(jq -r '.summary.added' out/audit-diff.json)" >> "$GITHUB_OUTPUT"
          echo "removed=$(jq -r '.summary.removed' out/audit-diff.json)" >> "$GITHUB_OUTPUT"
          echo "modified=$(jq -r '.summary.modified' out/audit-diff.json)" >> "$GITHUB_OUTPUT"

      # 4. Both SVG and audit-diff get bundled into a single artifact - the
      #    audit-pack handoff. Long retention (90d) so the pack stays
      #    available for the full audit cycle.
      - uses: actions/upload-artifact@v4
        id: upload
        with:
          name: compliance-audit-pack
          path: |
            out/diagram.svg
            out/audit-diff.json
          retention-days: 90

      - uses: peter-evans/find-comment@v3
        if: github.event_name == 'pull_request'
        id: find_comment
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-author: "github-actions[bot]"
          body-includes: "<!-- zindex-bot:compliance-pii-flow -->"

      - uses: peter-evans/create-or-update-comment@v4
        if: github.event_name == 'pull_request'
        with:
          comment-id: ${{ steps.find_comment.outputs.comment-id }}
          issue-number: ${{ github.event.pull_request.number }}
          edit-mode: replace
          body: |
            <!-- zindex-bot:compliance-pii-flow -->
            ### PII data-flow updated · revision ${{ steps.apply.outputs.rev }}

            | | |
            |---|---|
            | Changes since audit baseline | +${{ steps.diff.outputs.added }} / -${{ steps.diff.outputs.removed }} / ~${{ steps.diff.outputs.modified }} |
            | Revision | ${{ steps.prev_rev.outputs.rev }} → ${{ steps.apply.outputs.rev }} |
            | Baseline | revision `${{ secrets.AUDIT_BASELINE_REVISION }}` |

            <details><summary>Download audit pack (SVG + diff JSON)</summary>

            ${{ steps.upload.outputs.artifact-url }}

            </details>

            <sub>Rendered by Zindex · scene `${{ secrets.ZINDEX_SCENE_ID }}` · stamped with revision watermark</sub>
