# Data Access Group Grant Feishu Approval

This directory is the reviewed source for the Feishu approval definition used
by Helix data-access requests. Helix does not create or mutate this definition
at runtime. Feishu admins deploy the template manually, then store the resulting
approval code in Helix's `integration_approval_flows` mapping.

## Runtime Contract

- Flow key: `data_access_group_grant`
- Origin: Helix only
- External-origin submissions: disabled
- Callback URL: `/api/v1/approval/feishu/callback`
- Provider mutation owner: data-access BigQuery reconciler, never the Feishu
  callback path
- Approver-facing form: human-readable prose only. Raw semantic intent, owner
  context, compiled provider preview, and logging-style payload/compiler
  context stay in Helix's approval `source_payload` audit record and are not
  submitted as Feishu form fields.

## Deploy Options

Preferred production deploy path:

1. Run the manual GitHub Action
   `Deploy DAX Feishu Approval`.
2. Keep `dry_run=true` first and inspect the uploaded Feishu payload artifact.
3. Re-run with `dry_run=false` after approval. The workflow uses the existing
   prod Feishu app credentials from SSM, calls Feishu's v4 approval-definition
   API, stores the resulting
   `FEISHU_APPROVAL_DATA_ACCESS_GROUP_GRANT_CODE` back in SSM, and can upsert
   Helix's `integration_approval_flows` row on EC2 through
   `deploy/scripts/upsert-dax-approval-flow.sh`.

The workflow is manual/on-demand. It is not part of Helix runtime and does not
create approval definitions during normal app boot.

Manual Feishu console deploy remains supported:

1. Create a Feishu approval definition named `Helix BigQuery Dataset Access Request`.
2. Add the widgets from `definition.json` using the listed `custom_id` values.
   The field labels are written for approvers; do not replace them with raw
   JSON/audit labels.
   When using Feishu's v4 definition API, send labels and node names as the
   `@i18n@...` keys in `definition.json.feishu_v4_api_contract.i18n_keys` and
   include `i18n_resources`; Feishu rejects the update payload without those
   resources.
3. Configure the approver chain in Feishu with two ordered nodes:
   - `requester_line_manager_review`: Feishu's automatic requester line-manager
     approver. Helix does not send this approver because Feishu resolves it
     from the approval applicant/personnel record. In the Feishu v4 definition
     API this is an `AND` node whose approver is `{"type": "Supervisor",
     "level": "1"}`.
   - `data_owner_review`: a submitter-selected approver node whose node/custom
     id is `data_owner_review`. Helix resolves the request datasets' owners and
     submits them through `node_approver_open_id_list` when creating the
     approval instance. In the Feishu v4 definition API this is an `OR` node
     whose approver is `{"type": "Free"}` and
     `approver_chosen_multi=true`.

   Fixed approvers are acceptable only for disposable smoke-test templates that
   omit the `payload_schema.approval_process` block.
4. Publish the definition in Feishu and copy the resulting approval code.
5. Create or update the Helix `integration_approval_flows` row using
   `helix-flow-mapping.json`, replacing `REPLACE_WITH_FEISHU_APPROVAL_CODE`.
6. Ensure the Feishu app used by the Helix `chat_approval/feishu` integration
   has event subscription enabled for the callback URL above.

## Feishu v4 API Notes

For disposable local/test definitions, the verified endpoint is:

```text
POST /open-apis/approval/v4/approvals?user_id_type=open_id&department_id_type=open_department_id
```

Use `definition.json.feishu_v4_api_contract` as the reference shape, including
`i18n_resources`. The singular `/approval/v4/approval` path returns plain
`404 page not found` on the current Feishu host. To update an existing
disposable definition, include its `approval_code` in the POST body; to create a
new definition, omit it.

When Helix creates an instance for the dynamic owner node, it sends:

```json
{
  "node_approver_open_id_list": [
    {
      "key": "data_owner_review",
      "value": ["ou_xxx"]
    }
  ]
}
```

## Local Use

For local proof runs, use the same `payload_schema` from
`helix-flow-mapping.json` with the local stub Feishu integration. The local
`external_code` may be any stable local value because the stub does not call
Feishu.
