# DocuSeal — Operating Runbook
# Cold Bore Ballistics LLC — Internal Reference
# Classification: Confidential
# Last Updated: 2026-06-08

This runbook covers day-to-day operations of the DocuSeal e-signature service: sending documents, restarting the container, updating DocuSeal, and diagnosing the Logic App transfer flow.

DocuSeal runs as Azure Container App `ca-docuseal-prod` in `cae-cbb-prod`. All operational actions use the Azure CLI or the Azure Portal — there is no VM to SSH into.

---

## 1. Sending a Document for Signature

1. Open the DocuSeal web UI at `https://esign.coldboreballisticsllc.com`.
2. Log in with your DocuSeal admin account.
3. Click **New Document** or **Use Template** if a template exists.
4. Upload the document or select the template.
5. Add signers — enter name and email. Set signing order for multi-party documents if required.
6. Place signature fields by dragging them onto the document pages.
7. Click **Send** — signers receive an email with a signing link.
8. Monitor signing status from the DocuSeal dashboard.

**Verification:** When all signers have signed, the document status changes to **Signed**. Within a few minutes the signed PDF appears in:
- Azure Blob Storage: `stcbbprod/docuseal-docs/`
- OneDrive: `CBB_Corporate/03_-_Confidential/Legal_and_Trademarks/Signed_Agreements/`

If the file does not appear in OneDrive within 10 minutes, check the Logic App run history (Section 4).

---

## 2. Restarting DocuSeal

To restart the Container App:

```bash
az containerapp revision list \
  --name ca-docuseal-prod \
  --resource-group rg-cbb-prod \
  --output table
```

Note the active revision name, then restart it:

```bash
az containerapp revision restart \
  --name ca-docuseal-prod \
  --resource-group rg-cbb-prod \
  --revision <revision-name>
```

To check container logs:

```bash
az containerapp logs show \
  --name ca-docuseal-prod \
  --resource-group rg-cbb-prod \
  --tail 50
```

---

## 3. Updating DocuSeal

The Container App pulls from `crcbbprod.azurecr.io/docuseal/docuseal:latest`. The image is mirrored from Docker Hub into ACR — update ACR first, then trigger a new revision.

```bash
# Pull latest from Docker Hub and push to ACR
az acr login --name crcbbprod
docker pull docuseal/docuseal:latest
docker tag docuseal/docuseal:latest crcbbprod.azurecr.io/docuseal/docuseal:latest
docker push crcbbprod.azurecr.io/docuseal/docuseal:latest

# Trigger a new CA revision to pick up the updated image
az containerapp update \
  --name ca-docuseal-prod \
  --resource-group rg-cbb-prod \
  --image crcbbprod.azurecr.io/docuseal/docuseal:latest
```

This creates a new revision. DocuSeal runs database migrations automatically on startup. Monitor logs (Section 2) to confirm the new revision is healthy before the old one is deactivated.

---

## 4. Checking the Logic App Transfer Flow

The signed-document transfer is handled by the Logic App `logic-docuseal-onedrive-prod` in `rg-cbb-prod`. It polls `stcbbprod/docuseal-docs` every 1 minute, filters for `.pdf` files, retrieves the blob content, and PUTs it to Microsoft Graph (OneDrive drive `b!8KZ6l6zqUkWX3yo-OUxmhYeF60xdYy5MvDh1TzvtjdYp4zfMYleGQpITWXd0CY2l`) under `CBB_Corporate/03_-_Confidential/Legal_and_Trademarks/Signed_Agreements/`. It authenticates using the Logic App's system-assigned managed identity — no user account or connection credential required.

**Check run history via CLI:**

```bash
az logic workflow run list \
  --resource-group rg-cbb-prod \
  --workflow-name logic-docuseal-onedrive-prod \
  --output table
```

For detail on a specific run (replace `<run-name>` with the run ID from the list above):

```bash
az logic workflow run show \
  --resource-group rg-cbb-prod \
  --workflow-name logic-docuseal-onedrive-prod \
  --name <run-name>
```

**Monitor alert:** Run failures automatically email `jschwefel@coldboreballisticsllc.com` via the `ag-logic-app-failures-prod` action group (5-minute evaluation window).

**Common failure causes:**

| Symptom | Likely cause | Fix |
|---|---|---|
| Trigger fired but `Get_blob_content` and `Upload_to_SharePoint` skipped | `MediaType` filter not matching — do not use `endsWith(Name, '.pdf')` since DocuSeal blob names are random hashes with no extension; filter must use `equals(MediaType, 'application/pdf')` | Re-deploy `logic_app_definition` ARM deployment via `terraform apply -target=azurerm_resource_group_template_deployment.logic_app_definition` |
| Trigger did not fire | Blob was not written (DocuSeal storage misconfigured) | Check container app logs; verify `docuseal-storage-key` in KV matches `stcbbprod` |
| `Get_blob_content` failed | Storage account key rotated but KV secret not updated | Rotate `docuseal-storage-key` in KV, then re-deploy the `connection_azureblob` ARM deployment via `terraform apply` |
| `Upload_to_SharePoint` failed (403) | `Files.ReadWrite.All` app role not assigned to managed identity, or consent not granted | Re-run `terraform apply` — the `null_resource.logic_app_graph_role_assignment` provisioner will re-grant the role |
| `Upload_to_SharePoint` failed (404) | Drive ID or folder path is wrong | Verify drive ID and folder exist (see Rebuild Guide §9) |
| Logic App disabled | Workflow was stopped | `az logic workflow enable --resource-group rg-cbb-prod --name logic-docuseal-onedrive-prod` |

---

## 5. Checking Signed Document Storage

```bash
az storage blob list \
  --account-name stcbbprod \
  --container-name docuseal-docs \
  --auth-mode login \
  --output table
```

To download a specific document:

```bash
az storage blob download \
  --account-name stcbbprod \
  --container-name docuseal-docs \
  --name <blob-name> \
  --file ./downloaded.pdf \
  --auth-mode login
```

---

## 6. Rotating Secrets

All secrets are in `kv-cbb-shared-prod`. To rotate:

```bash
az keyvault secret set \
  --vault-name kv-cbb-shared-prod \
  --name <secret-name> \
  --value "<new-value>"
```

Then force a new Container App revision to pick up the updated secret:

```bash
az containerapp update --name ca-docuseal-prod --resource-group rg-cbb-prod
```

If the `stcbbprod` account key is rotated, update the KV secret and redeploy the blob API connection:

```bash
# 1. Rotate the key in Key Vault
STORAGE_KEY=$(az storage account keys list --account-name stcbbprod --resource-group rg-cbb-prod --query "[0].value" -o tsv)
az keyvault secret set --vault-name kv-cbb-shared-prod --name docuseal-storage-key --value "$STORAGE_KEY"

# 2. Redeploy the blob connection (picks up the new key from KV)
cd cbb-infra/services/cbb
terraform apply -target=azurerm_resource_group_template_deployment.connection_azureblob
```

---

## 7. Cold-Start / Warm-Up Behavior

The Container App is configured to scale to zero replicas when idle. After a period of inactivity, the first request will trigger a cold start: the container must spin up, load the Rails application, and establish its database connection before it can serve the request. This takes **30–60 seconds** and is expected behavior.

**Symptoms of a cold start:**
- The browser or API client hangs briefly, then loads normally
- A 502 or 503 error that resolves on retry within 60 seconds

**What to do:** Wait 60 seconds and retry. If the service does not respond after two retries, proceed to the normal restart procedure in §2.

**Do not** file a support ticket, escalate, or restart the container just because the first load is slow after a period of disuse.

---

*Cross-references: DocuSeal_Architecture_Reference.md (resource names and configuration), DocuSeal_Rebuild_Guide.md (full rebuild from scratch).*

---

## Document Control

| Field | Value |
|---|---|
| **Document owner** | `jschwefel@coldboreballisticsllc.com` |
| **Classification** | Confidential (03_-_Confidential/) |
| **Location** | `OneDrive/CBB_Corporate/03_-_Confidential/Infrastructure/DocuSeal/DocuSeal_Operating_Runbook.md` |
| **Cross-references** | `DocuSeal_Architecture_Reference.md`; `DocuSeal_Rebuild_Guide.md` |
| **Created** | 2026-06-07 |
| **Last updated** | 2026-06-10 |
| **Next full review due** | 2027-06-07 |

---

## Revision Control Block

| Rev | Date | Changed By | Reviewed By | Approved By | Summary |
|-----|------|------------|-------------|-------------|---------|
| 0.9 | 2026-06-07 | jschwefel | — | — | Initial release |
| 1.0 | 2026-06-08 | jschwefel | — | — | Replace Power Automate §4 with Logic App operations; update secret rotation §6; update document header |
| DRAFT | 2026-06-10 | jschwefel | — | — | Add §7 cold-start / warm-up behavior |
