diff --git a/.agents/skills/mavula-cloud-banking/SKILL.md b/.agents/skills/mavula-cloud-banking/SKILL.md new file mode 100644 index 0000000..444c3fb --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/SKILL.md @@ -0,0 +1,62 @@ +--- +name: mavula-cloud-banking +description: Design, implement, operate, and assess MAVULA as regulated cloud-native banking infrastructure. Use for real institutional workflows, module boundaries, financial operations, identity, payments, compliance, configurable and no-code products, composable APIs and events, production security, Kubernetes and AWS operations, resilience, observability, capacity, and high-scale readiness across all MAVULA repositories. +--- + +# MAVULA Cloud Banking + +Use this skill for engineering work that can affect institutional access, +financial state, payment state, regulatory evidence, runtime reliability, or +platform configuration. Ground every decision in repository contracts and +observable failure behavior. + +## Workflow + +1. Read the context map, invariants, touched contracts, migrations, runtime code, + tests, and deployment configuration. Distinguish implemented behavior from + roadmap intent. +2. Name the owner, caller, data classification, tenant boundary, financial + effect, consistency requirement, idempotency identity, audit evidence, and + recovery path. +3. Trace the full operation across synchronous APIs, owner transaction, + Outbox/Inbox, Workbench jobs, projections, monitoring, and operator action. +4. Define compatibility and failure behavior before implementation: timeout, + duplicate, reordering, partial failure, retry exhaustion, replay, rollback, + and reconciliation. +5. Quantify production assumptions per service: SLO, workload, peak concurrency, + data growth, RTO/RPO, failure domains, and capacity-test evidence. +6. Implement within the owner boundary using the repository's established + language, database, contract, migration, and guardian patterns. +7. Verify invariant tests, contract tests, security boundaries, failure paths, + observability, operational recovery, and CI-equivalent checks. + +## Hard Rules + +- Identity context is signed and authoritative. Payload identity never grants + tenant, institution, branch, role, or permission. +- `ledger-core` alone owns financial invariants and journal posting. Posted + records are immutable; correction uses controlled reversal or adjustment. +- `settlements` owns external payment state. A settlement event does not mutate + ledger or lending directly; an authorized ledger command is required. +- `workbench` owns operational jobs, not business truth. Retry is bounded and + every side effect is idempotent and auditable. +- PostgreSQL and owner aggregates are authoritative. Redis is transport and + temporary operational state. +- Public APIs and events are versioned contracts. Consumers never depend on + producer tables, private DTOs, or deployment internals. +- Configuration is declarative, tenant-scoped, versioned, validated, bounded, + approved where required, and immutable after publication. +- Production claims require measured evidence. Regulatory and certification + claims require explicit scope and accountable approval. + +## References + +- Module authority and allowed integration: `references/module-ownership.md`. +- Real institutional workflows and failure paths: `references/banking-operations.md`. +- Security, data protection, and regulatory baseline: `references/security-regulation.md`. +- Kubernetes, AWS, resilience, observability, and capacity: `references/cloud-native-scale.md`. +- API composability and governed no-code configuration: `references/composability-no-code.md`. +- Language, PostgreSQL, Redis, and COBOL rules: `references/engineering-data.md`. + +Load only the references relevant to the task. For reviews, use the companion +`mavula-review` skill so findings retain MAVULA severity and evidence format. diff --git a/.agents/skills/mavula-cloud-banking/agents/openai.yaml b/.agents/skills/mavula-cloud-banking/agents/openai.yaml new file mode 100644 index 0000000..bd7e02d --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "MAVULA Cloud Banking" + short_description: "Engineer regulated, composable cloud-banking systems" + default_prompt: "Use $mavula-cloud-banking to design or implement this MAVULA change with explicit ownership, financial invariants, security, recovery, operability, and scale evidence." diff --git a/.agents/skills/mavula-cloud-banking/references/banking-operations.md b/.agents/skills/mavula-cloud-banking/references/banking-operations.md new file mode 100644 index 0000000..33dcc9d --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/banking-operations.md @@ -0,0 +1,59 @@ +# Banking Operations + +## Institutional Access + +1. `identity-access` authenticates the operator or workload and derives effective + institution, branch, tenant, roles, and permissions from persisted state. +2. Resource servers validate issuer, audience, signature, expiry, token purpose, + tenant binding, and operation permission before reading request data. +3. Sensitive actions record actor, effective role, source, correlation, result, + and maker-checker evidence without placing credentials or unnecessary PII in events. + +## Product And Workflow Configuration + +1. An authorized configuration operator submits a schema-valid tenant-scoped draft. +2. The owner validates references, deterministic rules, limits, effective dates, + and approval policy before activation. +3. Publication creates an immutable version and audit record. Runtime operations + retain the exact product, rule, schema, and workflow versions used. +4. Rollback activates a known compatible version; it never mutates history. + +## Accounts, Ledger, And Lending + +1. Every write requires authenticated tenant context, correlation, and durable + idempotency when it can create a financial or external side effect. +2. The owner validates account/product state, currency, precision, limits, + maker-checker, and later-effect constraints inside one transaction. +3. Journal lines balance by currency. Subledger, audit, receipt, and Outbox are + committed atomically with the owner state. +4. Freeze, unfreeze, close, reversal, and correction preserve immutable history; + self-approval and duplicate approval are rejected. + +## Payments And Reconciliation + +1. Workbench starts an authorized payment job with tenant, correlation, amount, + rail, parties, and idempotency identity. +2. Settlements persists the process before external interaction and authenticates + callbacks before durable dedupe and explicit state transition. +3. Reconciliation compares provider, process, and expected ledger references. + Mismatch remains actionable and cannot be hidden by job success. +4. Settlement completion is recorded in Outbox and published by Workbench. + Ledger Core records Inbox idempotently and performs no direct financial + mutation from the event. + +## Regulatory And Legacy Processing + +1. An authorized compliance operator requests an export with period, legal basis, + retention, tenant, and idempotency context. +2. Ledger Core provides the approved source contract; Legacy Connectors generates + deterministic fixed-width content, totals, checksum, receipt, and artifact. +3. Workbench controls leases, bounded retries, DLQ, and delivery recording. + Imports remain staging and validation only unless a future owner command is approved. + +## Incident And Recovery + +- Diagnose owner state separately from queue state. A completed job does not prove + a completed business operation. +- Replay requires authorization, reason, original correlation, dedupe, and audit. +- Recovery verifies database consistency, Outbox/Inbox backlog, queue lag, DLQ, + settlement reconciliation, projection freshness, and regulatory artifact integrity. diff --git a/.agents/skills/mavula-cloud-banking/references/cloud-native-scale.md b/.agents/skills/mavula-cloud-banking/references/cloud-native-scale.md new file mode 100644 index 0000000..d3066a1 --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/cloud-native-scale.md @@ -0,0 +1,58 @@ +# Cloud-Native Scale + +## Service Readiness Budget + +Every production service or material change must document: + +- availability and latency SLOs with measured indicators and error-budget owner; +- normal, peak, burst, and degraded workload plus concurrency and tenant skew; +- data volume, growth, retention, hot-key or hot-tenant risk, and capacity horizon; +- RTO, RPO, backup frequency, restore procedure, and last recovery-test evidence; +- regional and zonal failure domains, dependency assumptions, and degradation mode; +- load, soak, fault, retry-storm, and recovery evidence at the claimed envelope. + +Do not invent one platform-wide number. Missing budgets invalidate production-ready +and scalable claims. + +## Kubernetes-Neutral Baseline + +- Keep domain services stateless between requests. Persist authority in owner + PostgreSQL and durable queues or stores designed for the required semantics. +- Define requests and limits, startup/readiness/liveness probes, graceful shutdown, + termination budgets, PodDisruptionBudget, topology spread, anti-affinity, and + horizontal scaling from measured saturation or backlog signals. +- Apply restricted workload security, non-root execution, read-only filesystems + where possible, explicit service accounts, NetworkPolicy, controlled egress, + signed immutable images, SBOM/provenance, and admission policy. +- Separate migrations from runtime rollout. Use expand/contract migrations, + bounded locks, compatibility windows, and tested rollback or forward-fix paths. +- Autoscaling must account for database connections, queue visibility/leases, + partition ordering, idempotency contention, and provider rate limits. + +## Data And Messaging Scale + +- Size PostgreSQL pools across all replicas; inspect plans, indexes, lock duration, + vacuum pressure, transaction age, replication lag, and backup/restore throughput. +- Partition only with a documented key, pruning evidence, migration path, and + tenant-skew analysis. Sharding never weakens owner invariants or auditability. +- Redis is non-authoritative. Namespace keys, define TTL and eviction behavior, + cap retries, monitor memory and queue lag, and design poison-message isolation. +- Outbox/Inbox publishers use leases, bounded batches, retry backoff, dedupe, and + backlog metrics. Backpressure must fail predictably instead of dropping work. + +## AWS Adapter + +- Keep AWS-specific resources in `operations`. Map the neutral baseline to EKS, + managed PostgreSQL, managed Redis, KMS, workload identity, Secrets Manager or + External Secrets, object storage, load balancing, and native audit telemetry. +- Verify multi-AZ behavior, encryption keys, IAM least privilege, private network + paths, egress controls, database failover, backup retention, restore testing, + quota limits, cost alarms, and regional recovery assumptions. + +## Observability And Operations + +Correlate tenant-safe metrics, logs, and traces with request, job, event, +idempotency, causation, and provider references. Alert on SLO burn, error rate, +latency, saturation, connection exhaustion, queue lag, DLQ, Outbox backlog, +projection lag, failed or expired payment processes, reconciliation mismatch, +migration failure, backup failure, and certificate or key expiry. diff --git a/.agents/skills/mavula-cloud-banking/references/composability-no-code.md b/.agents/skills/mavula-cloud-banking/references/composability-no-code.md new file mode 100644 index 0000000..89060f2 --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/composability-no-code.md @@ -0,0 +1,46 @@ +# Composability And Governed No-Code + +## Composable Boundaries + +- Expose capabilities through owner-controlled, versioned APIs, commands, events, + and file contracts with explicit schemas, permissions, errors, and idempotency. +- Prefer additive evolution. Breaking changes require a new version, migration + window, consumer inventory, compatibility tests, and deprecation evidence. +- Keep provider, cloud, channel, and legacy specifics behind adapters. Domain + modules depend on stable ports and business contracts, not vendor SDK objects. +- Use correlation and causation across boundaries. Do not leak database models, + internal enums, queue payloads, secrets, or unnecessary PII into public contracts. +- SDKs and Developer Docs are generated or verified against owner contracts and + provenance locks. Documentation cannot redefine owner behavior. + +## Configuration Lifecycle + +1. Create a tenant-scoped draft from an approved schema. +2. Validate syntax, types, references, permissions, limits, effective dates, + compatibility, and deterministic evaluation before persistence. +3. Preview or dry-run with synthetic or authorized data and no external side effects. +4. Require maker-checker for configurations that can change financial behavior, + access, settlement routing, compliance output, or external communication. +5. Publish an immutable version with actor, reason, correlation, content digest, + approval, and effective window. +6. Activate atomically. Running operations retain the exact version they used. +7. Roll back by activating a compatible prior version; never rewrite history. + +## Runtime Safety + +- Prohibit `eval`, `new Function`, arbitrary scripts, unrestricted templates, + dynamic SQL, filesystem/network access, and reflection-based class loading. +- Use an allowlisted expression or decision runtime with typed inputs/outputs, + deterministic time and rounding, complexity limits, execution timeout, memory + budget, recursion limit, and side-effect isolation. +- Validate money precision, currency, timezone, calendars, rate boundaries, + fee ordering, rule conflicts, workflow cycles, and unreachable states. +- Enforce authorization and tenant context during authoring, approval, activation, + execution, export, and rollback. A UI is not a security boundary. + +## No-Code Meaning + +For MAVULA, no-code means governed declarative products, rules, schemas, and +workflows. It does not mean arbitrary user code, direct database editing, or +unreviewed production activation. A future visual builder must emit the same +versioned contracts and pass the same validation and approval pipeline. diff --git a/.agents/skills/mavula-cloud-banking/references/engineering-data.md b/.agents/skills/mavula-cloud-banking/references/engineering-data.md new file mode 100644 index 0000000..6dfc885 --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/engineering-data.md @@ -0,0 +1,57 @@ +# Engineering And Data Standards + +## TypeScript And Node.js + +- Preserve strict public types, validated DTOs, async error propagation, bounded + concurrency, graceful shutdown, ESM/CJS compatibility, and workspace build order. +- NestJS scopes and guards must not leak request identity. Prisma client/schema/ + migration changes move together. BullMQ handlers are idempotent and lease-aware. + +## Go + +- Propagate `context.Context`, cancellation, deadlines, trace context, and tenant + authority through every boundary. Bound goroutines and channels; prove race safety. +- Wrap errors without losing classification. Use explicit interfaces, SQL + transactions, pool limits, deterministic clocks, and table-driven tests. + +## Java + +- Define Spring transaction boundaries, isolation, propagation, exception mapping, + bean scope, thread safety, pool limits, timeouts, and serialization compatibility. +- Avoid hidden lazy-loading, broad transactions, reflection-based configuration, + and retries around non-idempotent effects. Use contract and concurrency tests. + +## COBOL + +- Treat copybooks and fixed-width layouts as versioned wire contracts. Verify + encoding, exact offsets, `PIC` precision/scale, signs, packed decimal, overflow, + rounding, header/detail/trailer totals, checksums, and golden files. +- Batch execution is restartable from durable checkpoints. Duplicate input, + partial output, invalid trailer, and resume never duplicate financial effects. + +## Python + +- Require typed boundaries, reproducible packaging, parameterized SQL, deterministic + timezone and decimal handling, explicit resource cleanup, isolated tests, and + bounded memory for reporting or batch workloads. + +## PostgreSQL + +- Apply tenant RLS inside the same transaction and pooled connection as every + protected query. Runtime roles do not bypass RLS or own schemas. +- Keep financial effects, durable idempotency receipt, audit, and Outbox atomic. + Use constraints as invariants, indexes from measured queries, and online-safe + migrations with lock analysis, compatibility order, and recovery procedure. +- Test concurrent duplicate requests, deadlocks, serialization conflicts, pooled + connection reuse, cross-tenant access, rollback, and migration from real baselines. + +## Redis And Queues + +- Redis never becomes financial or identity truth. Namespace by environment and + tenant where applicable; define TTL, eviction, memory, and failover behavior. +- Jobs carry minimal authorized context, stable idempotency identity, correlation, + bounded retry/backoff, lease timeout, DLQ reason, replay policy, and metrics. + +Go and Java standards are ready for RFC-0003 modules but do not assign ownership +or justify migration by language preference alone. Choose language from workload, +correctness, interoperability, operational maturity, and team support evidence. diff --git a/.agents/skills/mavula-cloud-banking/references/module-ownership.md b/.agents/skills/mavula-cloud-banking/references/module-ownership.md new file mode 100644 index 0000000..07c856c --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/module-ownership.md @@ -0,0 +1,29 @@ +# Module Ownership + +## Authority + +| Boundary | Owns | Must not own | +| --- | --- | --- | +| `finance-platform` | Cross-module contracts, policy, submodule revisions, master guardian | Runtime financial or identity state | +| `identity-access` | Institutions, branches, operators, credentials, sessions, memberships, roles, OAuth/OIDC policy | Ledger accounts, payment state, job state | +| `ledger-core` | Tenant financial binding, products, accounts, journals, lending, financial workflows, audit, projections | Credentials, provider settlement state, queue truth | +| `settlements` | Payment processes, provider callbacks, dedupe, reconciliation, settlement Outbox | Journal posting, lending balances, operator identity | +| `workbench` | Jobs, schedules, attempts, leases, DLQ, publisher execution, platform status | Financial aggregates, provider state, identity policy | +| `legacy-connectors` | Copybooks, fixed-width layouts, batch receipts, artifacts, deterministic translation | Direct Identity or Ledger stores, financial mutation | +| `operations` | Kubernetes, AWS adapters, secrets wiring, migrations, backups, monitoring | Business aggregates or domain policy | +| `developer-docs` | Approved public contracts, integration guides, examples, provenance locks | Owner contract invention or private endpoint publication | + +## Integration Rules + +- Integrate through an owner API, authorized command, active event, or approved + versioned file contract. Never share or write another owner's tables. +- Commands carry authenticated tenant, actor, correlation, and idempotency + context. Events carry immutable facts and jobs carry operational work. +- Events use at-least-once delivery. Consumers dedupe persistently before effects. +- Read projections are rebuildable and eventually consistent. They are forbidden + for posting, balance mutation, lending approval, allocation, or settlement + decisions requiring current owner state. +- Cross-owner changes require producer and consumer compatibility tests, + explicit migration order, observability, and a rollback or forward-fix path. +- Ownership changes require an ADR, data migration, compatibility window, and + accountable approval. A folder move does not transfer authority. diff --git a/.agents/skills/mavula-cloud-banking/references/security-regulation.md b/.agents/skills/mavula-cloud-banking/references/security-regulation.md new file mode 100644 index 0000000..e871706 --- /dev/null +++ b/.agents/skills/mavula-cloud-banking/references/security-regulation.md @@ -0,0 +1,53 @@ +# Security And Regulation + +## Mandatory Platform Controls + +- Default deny at API, service, database, queue, and operator boundaries. +- Verify subject and workload identity for each protected resource; network + location is not authority. +- Derive tenant and permissions from signed identity context and enforce RLS in + the same transaction and connection as protected PostgreSQL access. +- Separate runtime, migration, backup, and operator credentials. Runtime roles do + not own schemas, bypass RLS, or receive migration secrets. +- Use least privilege, short-lived credentials, managed key rotation, TLS, secure + webhook verification, dependency provenance, and minimal CI permissions. +- Classify data, minimize event payloads, encrypt sensitive data, define retention + and deletion, and prevent secrets or PII from logs, metrics, traces, examples, + review comments, and `.env` tracking. +- Record append-only audit evidence for authentication, authorization, approvals, + configuration, posting, adjustment, settlement, export, replay, and failure. + +## Financial API Baseline + +- Treat OpenID FAPI 2.0 Security Profile and its attacker model as the target + baseline for high-value external APIs. Assess PAR, PKCE, sender-constrained + tokens, client authentication, redirect handling, key lifecycle, and resource + server behavior before claiming alignment. +- Use NIST SP 800-207 for zero-trust decisions and NIST SP 800-218 for secure + development and supply-chain evidence. +- Apply PCI DSS v4.0.1 only when cardholder data, sensitive authentication data, + or systems affecting that environment are in scope. First minimize and document scope. +- Use ISO 20022 for applicable external financial messaging profiles. It does not + replace MAVULA owner APIs, internal event envelopes, or local regulatory contracts. +- Use CNCF cloud-native security guidance for workload identity, orchestration, + image, runtime, storage, policy, and observability controls. + +## Mozambique Baseline + +- Use the primary Banco de Mocambique and statutory sources already approved in + RFC-0002 for AML/CFT/CPF, transaction records, retention, institutional conduct, + licensing, and credit-registry requirements. +- AML alerts, decisions, beneficial-owner data, suspicious-operation details, and + authority references are restricted need-to-know data, not free-form metadata. +- Preserve applicable records and investigations according to approved policy; + technical defaults never override a legal hold or authority instruction. +- Every legal interpretation, retention exception, reporting obligation, or + compliance claim requires current source verification and accountable legal or + compliance approval. Engineering evidence is not a legal opinion. + +## Required Threat Cases + +Test issuer/audience confusion, stolen or replayed tokens, privilege escalation, +cross-tenant access, self-approval, webhook replay, idempotency fingerprint +conflict, injection, SSRF, unsafe deserialization, secret leakage, dependency +compromise, queue poisoning, unauthorized replay, audit tampering, and backup exposure. diff --git a/.agents/skills/mavula-review/SKILL.md b/.agents/skills/mavula-review/SKILL.md new file mode 100644 index 0000000..c1d5d6c --- /dev/null +++ b/.agents/skills/mavula-review/SKILL.md @@ -0,0 +1,107 @@ +--- +name: mavula-review +description: Review MAVULA changes across finance-platform, identity-access, ledger-core, workbench, settlements, operations, legacy-connectors, and developer-docs. Use for pull request, security, database, migration, contract, cloud-native, scalability, no-code configuration, and production-readiness reviews in TypeScript, Go, Java, COBOL, Python, PostgreSQL, Redis, Kubernetes, AWS, and CI/CD. +--- + +# MAVULA Review + +Use this skill to review MAVULA changes against the platform's financial, +security, regulatory, and operational invariants. Findings require a concrete +failure mode and evidence; labels such as secure, compliant, cloud-native, or +scalable are never accepted without proof. + +## Required Context + +Read the relevant references from the companion skill before reviewing: + +- Ownership or cross-module changes: `../mavula-cloud-banking/references/module-ownership.md`. +- User or operator workflows: `../mavula-cloud-banking/references/banking-operations.md`. +- Authentication, authorization, data, AML, or regulatory changes: `../mavula-cloud-banking/references/security-regulation.md`. +- Deployments, queues, performance, availability, or production claims: `../mavula-cloud-banking/references/cloud-native-scale.md`. +- Product, rule, schema, workflow, or no-code changes: `../mavula-cloud-banking/references/composability-no-code.md`. +- Language, PostgreSQL, Redis, or batch changes: `../mavula-cloud-banking/references/engineering-data.md`. + +## Review Workflow + +1. Read the diff, surrounding code, tests, contracts, migrations, and CI configuration touched by the change. +2. Trace the complete operation from authenticated entry to owner transaction, + emitted contract, asynchronous processing, audit evidence, and recovery path. +3. Verify ownership, tenant isolation, financial invariants, compatibility, + failure handling, operability, capacity evidence, and regulatory applicability. +4. Confirm the smallest test set that proves the behavior, then run broader + guardian and CI-equivalent checks when the change crosses boundaries. +5. Report actionable findings only. Do not replace evidence with architecture + preference, praise, phase narration, or speculative rewrites. + +## Findings + +Lead with findings, ordered by severity. + +Use this shape: + +```text +[P1] Short imperative title +path/to/file.ext:line +Impact: concrete failure mode. +Fix: concrete change required. +Verification: command or test that should cover it. +``` + +Severity guide: + +- `P0`: exploitable security issue, cross-tenant disclosure, data loss, financial invariant break, or production-wide outage. +- `P1`: build/CI break, incorrect money movement, authorization bypass, unsafe migration, broken recovery, or production deploy blocker. +- `P2`: realistic runtime bug, replay/idempotency issue, race, capacity risk, observability gap, contract drift, or missing required test. +- `P3`: maintainability issue with concrete future cost. + +If there are no findings, say so directly and list residual risk or unrun validation. + +## Language + +Use the language already used in the pull request, issue, or discussion. If the thread is Portuguese, write formal Portuguese. If the thread is English or mixed technical code review, use concise professional English. + +Avoid marketing claims, decorative status symbols, phase narration, and long background explanations in review comments. + +## Non-Negotiable Review Gates + +- Reject tenant, institution, branch, role, or permission authority derived from + request payloads instead of verified identity context. +- Reject floating-point money, unbalanced journals, mutable posted entries, + self-approval, non-atomic audit, or duplicate effects for one idempotency key. +- Reject direct writes to another module's store and jobs or projections used as + the source of truth for command-side financial decisions. +- Reject webhook effects without signature validation, replay protection, + durable dedupe, explicit transitions, and reconciliation. +- Reject `eval`, `new Function`, mutable published configuration, or unbounded + expressions in configurable and no-code runtimes. +- Reject exactly-once assumptions. Require bounded retry, idempotent handlers, + poison-message handling, DLQ policy, authorized replay, and correlation. +- Reject production-ready or scalable claims without quantified service SLO, + workload, data growth, RTO/RPO, failure-domain, and capacity-test evidence. +- Reject compliance or certification claims without scope, control evidence, + responsible approval, and legal validation when required. +- Never expose credentials, tokens, private keys, customer data, or untracked + `.env` content in code or review output. + +## Validation Expectations + +Prefer the smallest validation set that proves the change. For this repository family, common checks include: + +```bash +pnpm guardian:check +pnpm contracts:check +pnpm -r build +git diff --check +``` + +For module changes, run the module guardian and targeted tests first. For +cross-repository changes, validate owner contracts, consumer compatibility, +master guardian, and initialized submodule parity. + +## Agent Behavior + +Do not approve your own change. Do not bypass branch protection unless an +authorized repository owner explicitly requests a narrowly scoped exception for +a concrete blocked merge. Checks and conversation resolution remain mandatory. + +When reviewing a pull request, keep the output review-shaped: findings first, then open questions, then validation notes. When implementing a fix, keep edits scoped to the issue, preserve unrelated local work, and update tests or guardian rules when the risk justifies it. diff --git a/.agents/skills/mavula-review/agents/openai.yaml b/.agents/skills/mavula-review/agents/openai.yaml new file mode 100644 index 0000000..46a0f43 --- /dev/null +++ b/.agents/skills/mavula-review/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "MAVULA Review" + short_description: "Review regulated banking changes against strict evidence gates" + default_prompt: "Use $mavula-review to review this MAVULA change for financial correctness, module ownership, tenant and data safety, security, contracts, operability, and production evidence." diff --git a/.cursor/rules/mavula-engineering.mdc b/.cursor/rules/mavula-engineering.mdc new file mode 100644 index 0000000..8063d6b --- /dev/null +++ b/.cursor/rules/mavula-engineering.mdc @@ -0,0 +1,12 @@ +--- +description: MAVULA regulated cloud-banking engineering and review guardrails +alwaysApply: true +--- + +Use `.agents/skills/mavula-cloud-banking/SKILL.md` for MAVULA architecture, +implementation, operations, security, scalability, composability, and no-code +configuration work. + +Use `.agents/skills/mavula-review/SKILL.md` for reviews. Production-impact +reviews must apply both skills. Lead with actionable findings ordered by +severity and use the language of the pull request, issue, or discussion. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c5857f8 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,9 @@ +# MAVULA Agent Instructions + +For architecture, implementation, operations, security, scalability, +composability, and no-code configuration, follow +`.agents/skills/mavula-cloud-banking/SKILL.md`. + +For reviews, follow `.agents/skills/mavula-review/SKILL.md` and load the relevant +cloud-banking references. Prioritize financial invariants, ownership, tenant and +data safety, security, recovery, capacity evidence, and CI reproducibility. diff --git a/.gitignore b/.gitignore index d5e0b2b..60388a7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,28 @@ coverage/ !.env.example *.log .DS_Store + +# Canonical MAVULA agent instructions +.agents/* +!.agents/skills/ +.agents/skills/* +!.agents/skills/mavula-review/ +.agents/skills/mavula-review/* +!.agents/skills/mavula-review/SKILL.md +!.agents/skills/mavula-review/agents/ +.agents/skills/mavula-review/agents/* +!.agents/skills/mavula-review/agents/openai.yaml +!.agents/skills/mavula-cloud-banking/ +.agents/skills/mavula-cloud-banking/* +!.agents/skills/mavula-cloud-banking/SKILL.md +!.agents/skills/mavula-cloud-banking/agents/ +.agents/skills/mavula-cloud-banking/agents/* +!.agents/skills/mavula-cloud-banking/agents/openai.yaml +!.agents/skills/mavula-cloud-banking/references/ +.agents/skills/mavula-cloud-banking/references/* +!.agents/skills/mavula-cloud-banking/references/module-ownership.md +!.agents/skills/mavula-cloud-banking/references/banking-operations.md +!.agents/skills/mavula-cloud-banking/references/security-regulation.md +!.agents/skills/mavula-cloud-banking/references/cloud-native-scale.md +!.agents/skills/mavula-cloud-banking/references/composability-no-code.md +!.agents/skills/mavula-cloud-banking/references/engineering-data.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..01b849f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ +# MAVULA Agent Entry Point + +Use `.agents/skills/mavula-cloud-banking/SKILL.md` for architecture, implementation, +production readiness, security, operations, scalability, and configurable banking +workflows. + +Use `.agents/skills/mavula-review/SKILL.md` for pull request, security, database, +migration, contract, and production-readiness reviews. Production-impact reviews +must also load the relevant `mavula-cloud-banking` reference. + +Keep `.agents` limited to canonical reusable instructions. Never add transcripts, +local prompts, generated reports, credentials, or temporary agent state. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d272f8b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,10 @@ +# MAVULA Agent Instructions + +Follow `AGENTS.md` as the repository-wide entry point. + +Use `.agents/skills/mavula-cloud-banking/SKILL.md` for architecture, +implementation, operations, security, scalability, composability, and no-code +configuration. Use `.agents/skills/mavula-review/SKILL.md` for reviews and load +the relevant cloud-banking references for production-impact changes. + +Do not create additional Claude instruction files or rules in this repository. diff --git a/package.json b/package.json index 6e02cdb..9ecc7d4 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "scripts": { "build": "tsc -p tsconfig.json", - "guardian:check": "node scripts/guardian.mjs", + "guardian:check": "node scripts/guardian.mjs && node --test scripts/check-agent-policy.test.mjs", "test": "tsc -p tsconfig.json && node --test test/*.test.mjs", "test:ci": "tsc -p tsconfig.json && node --test test/*.test.mjs", "typecheck": "tsc -p tsconfig.json --noEmit", diff --git a/scripts/check-agent-policy.mjs b/scripts/check-agent-policy.mjs new file mode 100644 index 0000000..13245a5 --- /dev/null +++ b/scripts/check-agent-policy.mjs @@ -0,0 +1,117 @@ +import { existsSync, readFileSync } from "node:fs"; +import { spawnSync } from "node:child_process"; +import { createHash } from "node:crypto"; +import { join } from "node:path"; + +export const canonicalAgentFiles = Object.freeze([ + "AGENTS.md", + ".agents/skills/mavula-review/SKILL.md", + ".agents/skills/mavula-review/agents/openai.yaml", + ".agents/skills/mavula-cloud-banking/SKILL.md", + ".agents/skills/mavula-cloud-banking/agents/openai.yaml", + ".agents/skills/mavula-cloud-banking/references/module-ownership.md", + ".agents/skills/mavula-cloud-banking/references/banking-operations.md", + ".agents/skills/mavula-cloud-banking/references/security-regulation.md", + ".agents/skills/mavula-cloud-banking/references/cloud-native-scale.md", + ".agents/skills/mavula-cloud-banking/references/composability-no-code.md", + ".agents/skills/mavula-cloud-banking/references/engineering-data.md", +]); + +export const canonicalAgentAdapters = Object.freeze([ + ".cursor/rules/mavula-engineering.mdc", + ".github/copilot-instructions.md", + "CLAUDE.md", +]); + +export const canonicalAgentDigests = Object.freeze({ + "AGENTS.md": "8ea1de953a05a947f0cbe5a05ea0c5d4d98ef5fa5121611cc319cad5fcec2a86", + ".agents/skills/mavula-review/SKILL.md": "225491092735e63ae996ee56ea550ca8a3385688b577a34c1ca3346ae32fd8f1", + ".agents/skills/mavula-review/agents/openai.yaml": "8d9e7ded6558f9c57032d4654385fcf889911dbec3108c736d377ff31b536b1a", + ".agents/skills/mavula-cloud-banking/SKILL.md": "610a2f2154839389aa67c550c17cde9f72296b012f2e89006937bf64c41ef355", + ".agents/skills/mavula-cloud-banking/agents/openai.yaml": "0eceb6e2d4ce0ee09754bea0cb3ce71a96c22a2f1c3a62202c1561be0f1bcefd", + ".agents/skills/mavula-cloud-banking/references/banking-operations.md": "000f033ca5810368513c0e53812ee9ee489565cb7b6c6589cce6ddb21748e39f", + ".agents/skills/mavula-cloud-banking/references/cloud-native-scale.md": "54ff285d608844090883d2535988980fe84f398a6654c1e5ba1cfa52bccecb1a", + ".agents/skills/mavula-cloud-banking/references/composability-no-code.md": "2a05a498b1145c13dd77f83746fab906fae7dacaa8f177e30a8b537e805bff6c", + ".agents/skills/mavula-cloud-banking/references/engineering-data.md": "1f8ead9ddd44a67e4c5db465ad1da4f15495dc40d8c079ca88737683fe372534", + ".agents/skills/mavula-cloud-banking/references/module-ownership.md": "b8f1f85b54e1b0878912e76d377c9b1484c7a685ee6299344429e4b7d8c67eb9", + ".agents/skills/mavula-cloud-banking/references/security-regulation.md": "7f6ed9f897b1b6acf98e29687f4744da8fbdf21edfef8f75f217f938edb7bb20", + ".cursor/rules/mavula-engineering.mdc": "5808eae2c61ed71c9986f238a8df46a2dd5d47fdb144dfdb5d1ab59e8845a736", + ".github/copilot-instructions.md": "e559442e010dd5baf747999f51e828bf9224c4a990cb83c0322f99986cbe87e1", + "CLAUDE.md": "b450943d31e250744342e8162d2418883ce8f3792a863e5d3353ef94f7c2fd13", +}); + +function sha256(file) { + return createHash("sha256").update(readFileSync(file)).digest("hex"); +} + +export function enforceLocalAgentPolicy({ root = "." } = {}) { + const failures = []; + const required = [...canonicalAgentFiles, ...canonicalAgentAdapters]; + for (const file of required) { + if (!existsSync(join(root, file))) failures.push(`${file} is required`); + } + + const tracked = spawnSync("git", ["ls-files"], { cwd: root, encoding: "utf8" }); + if (tracked.status !== 0) return ["git ls-files failed for agent policy"]; + const trackedFiles = new Set(tracked.stdout.split("\n").filter(Boolean)); + + for (const file of required) { + if (!trackedFiles.has(file)) failures.push(`${file} must be tracked`); + const absolutePath = join(root, file); + if (!existsSync(absolutePath)) continue; + const expectedDigest = canonicalAgentDigests[file]; + if (!expectedDigest) { + failures.push(`${file} has no approved canonical digest`); + } else if (sha256(absolutePath) !== expectedDigest) { + failures.push(`${file} differs from the approved canonical content`); + } + } + + const allowedAgents = new Set(canonicalAgentFiles); + for (const file of trackedFiles) { + if (file === ".cursorrules") { + failures.push(`${file} conflicts with the canonical Cursor policy`); + } + if (file.startsWith(".agents/") && !allowedAgents.has(file)) { + failures.push(`${file} is not part of the canonical agent policy`); + } + if (file.startsWith(".cursor/rules/") && file !== canonicalAgentAdapters[0]) { + failures.push(`${file} is not part of the canonical Cursor policy`); + } + if (file.startsWith(".github/instructions/")) { + failures.push(`${file} is not part of the canonical Copilot policy`); + } + if (file.startsWith(".claude/")) { + failures.push(`${file} conflicts with the canonical Claude policy`); + } + const basename = file.split("/").at(-1); + if ( + (["AGENTS.md", "AGENTS.override.md"].includes(basename) && file !== "AGENTS.md") + || (basename === "CLAUDE.md" && file !== "CLAUDE.md") + ) { + failures.push(`${file} conflicts with the root agent entry point`); + } + if (file === ".vscode/settings.json") { + const settings = readFileSync(join(root, file), "utf8"); + if (/"(?:chat\.instructionsFilesLocations|github\.copilot\.chat\.[^"]*\.instructions)"\s*:/.test(settings)) { + failures.push(`${file} contains an alternate VS Code instruction source`); + } + } + } + + for (const file of [ + "AGENTS.md", + ".cursor/rules/mavula-engineering.mdc", + ".github/copilot-instructions.md", + "CLAUDE.md", + ]) { + const absolutePath = join(root, file); + if (!existsSync(absolutePath)) continue; + const content = readFileSync(absolutePath, "utf8"); + for (const skill of ["mavula-review", "mavula-cloud-banking"]) { + if (!content.includes(skill)) failures.push(`${file} must route to ${skill}`); + } + } + + return failures; +} diff --git a/scripts/check-agent-policy.test.mjs b/scripts/check-agent-policy.test.mjs new file mode 100644 index 0000000..0b3f1c1 --- /dev/null +++ b/scripts/check-agent-policy.test.mjs @@ -0,0 +1,92 @@ +import assert from "node:assert/strict"; +import { cpSync, mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { spawnSync } from "node:child_process"; +import test from "node:test"; +import { fileURLToPath } from "node:url"; +import { + canonicalAgentAdapters, + canonicalAgentFiles, + enforceLocalAgentPolicy, +} from "./check-agent-policy.mjs"; + +const sourceRoot = join(dirname(fileURLToPath(import.meta.url)), ".."); + +function withPolicyRepository(mutate, verify) { + const root = mkdtempSync(join(tmpdir(), "mavula-agent-policy-")); + try { + for (const file of [...canonicalAgentFiles, ...canonicalAgentAdapters]) { + const target = join(root, file); + mkdirSync(dirname(target), { recursive: true }); + cpSync(join(sourceRoot, file), target); + } + mutate(root); + const initialized = spawnSync("git", ["init", "-q"], { cwd: root, encoding: "utf8" }); + assert.equal(initialized.status, 0, initialized.stderr); + const staged = spawnSync("git", ["add", "."], { cwd: root, encoding: "utf8" }); + assert.equal(staged.status, 0, staged.stderr); + verify(enforceLocalAgentPolicy({ root })); + } finally { + rmSync(root, { force: true, recursive: true }); + } +} + +function write(root, file, content = "conflicting instructions\n") { + const target = join(root, file); + mkdirSync(dirname(target), { recursive: true }); + writeFileSync(target, content); +} + +test("accepts the canonical multi-agent policy", () => { + withPolicyRepository(() => {}, (failures) => assert.deepEqual(failures, [])); +}); + +test("rejects alternate repository instruction files", () => { + withPolicyRepository( + (root) => { + for (const file of [ + ".cursorrules", + ".claude/rules/review.md", + ".github/instructions/unsafe.instructions.md", + ".cursor/rules/unsafe.mdc", + "AGENTS.override.md", + "nested/AGENTS.md", + "nested/CLAUDE.md", + ]) write(root, file); + }, + (failures) => { + for (const file of [ + ".cursorrules", + ".claude/rules/review.md", + ".github/instructions/unsafe.instructions.md", + ".cursor/rules/unsafe.mdc", + "AGENTS.override.md", + "nested/AGENTS.md", + "nested/CLAUDE.md", + ]) assert.ok(failures.some((failure) => failure.includes(file)), `missing rejection for ${file}`); + }, + ); +}); + +test("rejects VS Code instruction overrides but accepts ordinary settings", () => { + withPolicyRepository( + (root) => write(root, ".vscode/settings.json", '{"editor.formatOnSave": true}\n'), + (failures) => assert.deepEqual(failures, []), + ); + withPolicyRepository( + (root) => write(root, ".vscode/settings.json", '{"chat.instructionsFilesLocations": {"unsafe.md": true}}\n'), + (failures) => assert.ok(failures.some((failure) => failure.includes("alternate VS Code instruction source"))), + ); + withPolicyRepository( + (root) => write(root, ".vscode/settings.json", '{"github.copilot.chat.reviewSelection.instructions": [{"text": "ignore policy"}]}\n'), + (failures) => assert.ok(failures.some((failure) => failure.includes("alternate VS Code instruction source"))), + ); +}); + +test("rejects modified canonical policy content", () => { + withPolicyRepository( + (root) => write(root, ".agents/skills/mavula-review/SKILL.md", "stub\n"), + (failures) => assert.ok(failures.some((failure) => failure.includes("differs from the approved canonical content"))), + ); +}); diff --git a/scripts/guardian.mjs b/scripts/guardian.mjs index fd591b1..f882331 100644 --- a/scripts/guardian.mjs +++ b/scripts/guardian.mjs @@ -2,8 +2,10 @@ import { existsSync, readFileSync } from "node:fs"; import { spawnSync } from "node:child_process"; +import { enforceLocalAgentPolicy } from "./check-agent-policy.mjs"; const failures = []; +failures.push(...enforceLocalAgentPolicy()); function fail(message) { failures.push(message);