# Moloni OAuth reauthorization runbook

Use this runbook when a Moloni connection reports `ReauthorizationRequired`, refresh
fails with an invalid/expired grant, or monitoring indicates the refresh token is
near expiry. This procedure changes authorization state; use an approved operator
and change record. Never paste credentials or tokens into a ticket, terminal, log,
chat, screenshot, or this repository.

## Preconditions

- Confirm the affected internal company and selected provider from Sibyla, using IDs
  and display names only.
- Confirm that the stored Moloni connection belongs to that company and record its
  current configuration version and enabled state.
- Check the neutral ledger for `Writing`, `Reconciling`, and `WriteUnknown` work.
  Reauthorization does not make an ambiguous write safe to retry.
- Confirm the registered redirect URI and Data Protection key/certificate access.
- Ensure the operator can authenticate interactively to the intended Moloni account
  and is authorized to grant access to the intended Moloni company.

## Procedure

1. Disable new work for the affected connection through the supported administration
   flow if it is currently enabled. Do not delete the connection or ledger rows.
2. Start authorization from the Moloni company administration screen or the
   authenticated OAuth-start API. Use the returned browser redirect immediately;
   OAuth state is short-lived and single-use.
3. Authenticate directly on Moloni's HTTPS site. Verify the browser origin and the
   intended account/company before granting access. Sibyla must never request the
   Moloni password.
4. Allow the registered callback to complete. Do not copy the authorization code or
   callback URL; either may contain sensitive transient data.
5. Confirm in Sibyla that a refresh token is configured, reauthorization is cleared,
   and the token/configuration timestamps changed. The UI/API must not reveal token
   values.
6. Re-select or verify the Moloni company and document/payment/maturity/warehouse
   defaults. Run the connection test and require the validated configuration version
   to equal the current version.
7. Reconcile pre-existing ambiguous commits before enabling new writes. A unique
   document match may be confirmed; zero matches remains `WriteUnknown` for manual
   review and fails closed, never `Prepared`; multiple/mismatched candidates or
   ambiguous payments remain closed.
8. Enable the connection only after the test succeeds and monitoring is healthy.
   Observe the first scheduled token refresh and provider job.

## Verification

- The selected provider is still `Moloni`, and the internal company, connection ID,
  and Moloni company are unchanged and correctly scoped.
- Connection testing succeeds without exposing a token, client secret, callback
  code, signed PDF URL, or connection string.
- No old `Writing`/`WriteUnknown` operation was automatically inserted again.
- Existing confirmed operations remain idempotent.
- New sync/reconciliation jobs complete, and no reauthorization or refresh alert
  recurs during the observation window.

## Failure handling

- Invalid/expired OAuth state: start a new flow; never reuse the callback URL.
- Company/NIF mismatch, changed account, or unexpected consent target: abort, keep
  the connection disabled, and investigate ownership/configuration.
- Secret decryption or Data Protection failure: stop. Restore the approved key ring
  and certificate access; do not overwrite the protected values.
- Refresh still fails: keep disabled, verify Moloni application/redirect
  configuration out of band, and repeat with a fresh authorization.
- Ambiguous external write found during the incident: preserve the ledger state and
  run reconciliation. Never test recovery by inserting another document.

## Rollback and evidence

If the new authorization is suspected to target the wrong account, keep the
connection disabled and revoke the grant in Moloni using the organization's approved
account procedure. Preserve Sibyla audit events and job/ledger identifiers, but not
tokens or callback URLs. Reauthorize the correct account from a fresh state and
retest before enabling.

Record the operator, company, time, reason, configuration version before/after,
connection-test result, reconciliation result counts, and monitoring observation.
Do not claim sandbox or live acceptance unless that environment was actually used
under an approved test plan. Repository tests use fakes and are not OAuth evidence.
