Skip to content

docs: build complete MAVULA API portal - #3

Merged
EstandarMustaq merged 1 commit into
rfc-0002-legacy-batch-guidesfrom
docs/complete-use-case-portal
Jul 16, 2026
Merged

docs: build complete MAVULA API portal#3
EstandarMustaq merged 1 commit into
rfc-0002-legacy-batch-guidesfrom
docs/complete-use-case-portal

Conversation

@EstandarMustaq

@EstandarMustaq EstandarMustaq commented Jul 15, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces generic generated pages with an Astro and Starlight portal
  • Renders three owner OpenAPI contracts locally with Scalar
  • Covers authentication, tenant isolation, financial controls, payments, configuration, projections, and legacy batches
  • Adds curl, TypeScript, Python, Java, Go, and Postman examples
  • Publishes through GitHub Pages Actions without a hosted request console

Contract dependencies

Publication dependency

Validation

  • Guardian and owner digest checks pass
  • Contract tests pass
  • Production build succeeds with 26 pages
  • 6 Playwright tests pass across desktop and mobile

@EstandarMustaq
EstandarMustaq marked this pull request as ready for review July 15, 2026 19:17
@EstandarMustaq
EstandarMustaq requested a review from a team as a code owner July 15, 2026 19:17
@EstandarMustaq
EstandarMustaq requested review from YasserBoaventura and removed request for a team July 15, 2026 19:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

contract_id: { type: string, const: 'legacy.regulatory_transaction_export@1' }

P2 Badge Allow import receipts to use an import contract id

When POST /api/legacy-imports returns LegacyBatchCreated, it uses this LegacyBatchReceipt schema, but the schema allows direction: IMPORT while forcing every receipt's contract_id to the regulatory export contract. Valid import receipts will fail generated-client/schema validation, or clients will be unable to distinguish imports from exports by contract; allow the import contract id as well or split the receipt schemas.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +12 to +14
| Identity Access | `https://identity.mavula.io` | OAuth 2.0 and OpenID Connect |
| Ledger Core | `https://ledger.mavula.io` | Synchronous commands and reads |
| Workbench | `https://workbench.mavula.io` | Asynchronous jobs and operational reads |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align guide hosts with the OpenAPI servers

For users copying the new v1 overview/examples, these base URLs send them to *.mavula.io, but the same commit's public OpenAPI contracts still advertise https://identity.mavula.dev, https://ledger.mavula.dev, and https://workbench.mavula.dev as their servers (openapi/*:12), so the portal points manual integrations/Postman at a different environment than Scalar/client generation. Please use one canonical host family in both the guides/collection and OpenAPI contracts.

Useful? React with 👍 / 👎.

throw new Error('retry budget exhausted');
```

See [Idempotency and retries](../concepts/idempotency/) for receipt and conflict semantics.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fix the broken idempotency link

On the request-reliability page, this relative link resolves from /v1/getting-started/request-reliability/ to /v1/getting-started/concepts/idempotency/, but the page exists at /v1/concepts/idempotency/. Users clicking it from the published portal will hit a 404; change the target to ../../concepts/idempotency/.

Useful? React with 👍 / 👎.

Comment on lines +12 to +15
| `operations_viewer` | Read operational and financial state | `finance.read` |
| `operations_maker` | Submit controlled changes | `finance.read`, `finance.write` |
| `operations_checker` | Approve or reject controlled changes | `finance.read`, `finance.approve` |
| `compliance_officer` | Review and generate regulated outputs | `finance.read`, `compliance.read`, `compliance.write` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align role permissions with operation requirements

For users provisioning the documented minimum roles, the listed permissions do not satisfy the new x-mavula-permissions contract: operational reads in Workbench require workbench.read, and every legacy/regulatory operation requires compliance.manage, but this table grants only finance.read to operations_viewer and compliance.read/compliance.write to compliance_officer. Those roles will get 403s for the workflows they are documented to cover; update the table to use the actual permissions.

Useful? React with 👍 / 👎.

-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 0e03ef93-09e0-413f-b49a-e59f93fa881f' \
-H 'X-Correlation-ID: bd351e46-e436-4dd2-b9de-75e940629961' \
-d '{"report_type":"TRANSACTION_ACTIVITY","period_start":"2026-06-01","period_end":"2026-06-30","format":"CSV"}'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update regulatory export examples to the schema

When users copy this regulatory export command, Workbench rejects it because the new CreateRegulatoryExport schema has additionalProperties: false and requires period_from, period_to, legal_basis_code, and retention_until; this payload sends old report_type/period_start/period_end/format fields instead. The delivery example below has the same drift (authority_reference is required), so both examples need to match workbench.public.v1.yaml.

Useful? React with 👍 / 👎.

-H 'Content-Type: application/json' \
-H 'Idempotency-Key: bfe8b575-2137-4a86-a210-cc2182130aed' \
-H 'X-Correlation-ID: fd662f62-19c7-4f92-941f-64667437e6f9' \
-d '{"type":"PAYMENT_PROCESS","payload":{"tenant_id":"tenant_001","idempotency_key":"payment_001","correlation_id":"fd662f62-19c7-4f92-941f-64667437e6f9","rail":"BANK_TRANSFER","amount":"2500.00","payer":{"account_id":"account_001"},"payee":{"bank_account":"000123456789"}}}'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replace the stale payment job payload

This payment example no longer matches the contract: CreateJob.type is restricted to PAYMENT_CAPTURE, PAYMENT_DISBURSEMENT, PAYMENT_SETTLEMENT, or PAYMENT_RECONCILIATION, while the sample sends PAYMENT_PROCESS, and the payload also uses BANK_TRANSFER, a decimal-string amount, and payer/payee shapes that do not match the schema. Copying the guide will produce a 400 instead of creating a job.

Useful? React with 👍 / 👎.

"header": [
{ "key": "Authorization", "value": "Bearer {{access_token}}" },
{ "key": "Content-Type", "value": "application/json" },
{ "key": "Idempotency-Key", "value": "{{$guid}}" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve idempotency keys across Postman retries

Postman dynamic variables such as {{$guid}} are generated when the request runs, so clicking Send again after a timeout creates a different Idempotency-Key for the same logical account/freeze command. That bypasses the retry receipt semantics documented elsewhere and can create duplicate mutations; store the key in a collection/environment variable instead of using {{$guid}} directly on mutating requests.

Useful? React with 👍 / 👎.

--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=YOUR_CLIENT_ID' \
--data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \
--data-urlencode 'scope=openid finance.read finance.write'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose finance scopes on service-token flow

The quickstart's client_credentials request asks for openid finance.read finance.write, but the OpenAPI clientCredentials flow only declares internal.worker as an allowed scope. Generated clients and Scalar auth for the service-token flow will not offer the finance scopes required by the subsequent Ledger Core calls, and an OAuth server following the contract can reject this token request; either add the service scopes to this flow or change the quickstart to a declared scope.

Useful? React with 👍 / 👎.

Comment on lines +763 to +765
allOf:
- $ref: '#/components/schemas/CreateFinancialAdjustment'
- type: object

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t compose closed request schemas into responses

For clients that validate responses against this contract, FinancialAdjustmentRequest can never validate a normal response: the referenced CreateFinancialAdjustment schema has additionalProperties: false, so response fields added by the second allOf branch such as id, status, and requested_by are rejected as additional properties. The same closed-schema extension pattern appears on Rule, EntitySchema, and Workflow; move the closure to the composed response schema or define full response schemas separately.

Useful? React with 👍 / 👎.

description: Submit tenant-scoped payment work. The tenant is always derived from the access token.
tags: [Jobs]
x-mavula-permissions: [workbench.jobs.write]
requestBody:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Declare idempotency on job submission

Unlike the other mutating Workbench operations and the payment guide, POST /api/jobs has no Idempotency-Key or X-Correlation-ID parameters in the public contract. Generated clients from this OpenAPI file will omit the retry key when submitting payment jobs, so retrying after a lost response can enqueue duplicate work instead of returning the original job receipt.

Useful? React with 👍 / 👎.

@EstandarMustaq
EstandarMustaq merged commit 1a8a26e into rfc-0002-legacy-batch-guides Jul 16, 2026
2 checks passed
EstandarMustaq added a commit that referenced this pull request Jul 16, 2026
* docs: publish legacy batch integration guide

* docs: build complete public API portal (#3)
EstandarMustaq added a commit that referenced this pull request Jul 16, 2026
* feat: publish versioned public api reference

* chore: sync licensed owner contracts

* RFC-0002: publish legacy batch documentation (#2)

* docs: publish legacy batch integration guide

* docs: build complete public API portal (#3)

* ci: harden Pages deployment permissions

* fix: align portal guides with public contracts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant