# Schema Documentation ## Why Schemas Matter This service is driven by JSON schemas stored in S3. The Python code is the execution engine, but route behavior, authentication options, validation rules, business rules, database writes, and responses are defined outside this repository. Full service documentation must include both: - Python execution engine documentation - S3 schema documentation ## S3 Schema Types ### Route Schema Path: ```text api_wrapper/api/routes.json ``` Used by: ```text routes.py authentication.py ``` Purpose: - Define endpoint paths - Define HTTP methods - Define whether authentication is required - Define supported auth types - Define optional IP whitelist behavior - Group routes by app name, such as `test1` and `mconnect` Expected shape based on code usage: ```json { "mconnect": { "/api/example": { "method": "post", "auth": ["basic", "jwt"], "ip_check_enabled": true } } } ``` Only fields read by the current code are shown here. The actual S3 schema may include additional fields. ### Authentication Schema Path: ```text api_wrapper/authentication/authentication_schema.json ``` Used by: ```text authentication.py ``` Purpose: - Define allowed host/domain prefixes - Define supported authentication entries per domain - Define DB-backed Basic credential lookup - Define JWT header, algorithm, decode key, and verification query - Define IP whitelist query details - Define invalid auth response content Expected shape based on code usage: ```json { "domain": { "mconnectuat": { "authentication": [ { "type": "basic", "mode": "database", "storedKey": { "queryType": "select", "table": "merchant_api_keys", "columns": ["merchant_id"], "clause": { "where": ["client_id", "client_secret"], "queryParams": ["$auth.client_id", "$auth.client_secret"], "logicalOperator": "and", "valueOperator": "=" } } } ], "IPwhitelisting": { "queryType": "select", "table": "merchant_ip_whitelist", "columns": ["ips"], "clause": { "where": ["merchant_id"], "queryParams": ["$merchant_id"] } }, "response": { "basic": { "content": { "application/json": {}, "status_code": 401 } } } } } } ``` This is an illustrative structure inferred from the local Python code. Confirm exact fields against the S3 object before changing production behavior. ### Endpoint Behavior Schema Selected by: ```text main.py ``` Possible paths: ```text api_wrapper/{source}/{domain}/category/default/default.json api_wrapper/merchant/{merchant_id}/{domain}/{merchant_name}.json api_wrapper/category/{category_id}/{domain}/{category_name}.json ``` Purpose: - Define request validation - Define init and post-validation functions - Define business rules - Define persistence blocks - Define responses for `cf_code` values Expected endpoint section: ```json { "paths": { "/api/example": { "post": { "requestBody": { "content": {}, "rules": { "data": [] } }, "functions": { "init": [], "someFunction": [] }, "persistence": [], "responses": { "CF200": { "content": { "application/json": {}, "status_code": 200 }, "actions": [] } } } } } } ``` ## Endpoint Schema Sections ### `requestBody.content` JSON Schema used by `jsonschema.validate()`. Field-level validation messages can be embedded in schema properties through a `message` object. `schema_validation.py` attempts to read: ```json { "message": { "message": "Human readable message", "return_code": "00000" } } ``` ### `requestBody.rules.data` Business rules evaluated before persistence. Rules use conditions and true/false branches. Representative rule: ```json { "conditions": ["$request.amount", "greaterThan", "100000"], "true": { "operation": "returnResponse", "return_code": "LIMIT_EXCEEDED", "message": "Amount is above allowed limit", "CF_code": "CF300" } } ``` ### `functions` Function blocks run through `DryRunFunction`. - `init` runs before validation. - All other function blocks run after rules pass. Function blocks can contain operations or nested conditions. ### `persistence` Persistence blocks run after validation, rules, and functions pass. They can be unconditional: ```json { "operation": "query", "queryType": "insert", "table": "example_table", "values": { "name": "$request.name" }, "auto_id": "id" } ``` Or conditional: ```json { "conditions": ["$request.hasAddress", "equals", true], "true": { "queryType": "insert", "table": "address", "values": { "line1": "$request.address.line1" } } } ``` ### `responses` Response blocks are selected by `cf_code`. Representative response: ```json { "CF200": { "content": { "application/json": { "status": "success", "application_id": "$consumer_application_id" }, "status_code": 200 }, "actions": [] } } ``` Response values can use key resolution and component calls. ## Schema Review Checklist Use this checklist for every schema change: - Route exists under the correct app group. - Route method matches Flask/client method. - Auth modes match domain auth schema. - Host prefix exists in auth schema. - Merchant/category/admin schema path will resolve correctly. - JSON Schema includes messages for user-facing validation failures. - Rule branches return correct `CF_code`. - All `$request`, `$env`, `$auth`, `$token`, and state references resolve. - DB queries use parameterized values through `queryParams` or `values`. - Raw SQL is reviewed carefully. - Response block exists for every possible `cf_code`. - Response `status_code` matches expected client behavior. - External API calls have timeout/credential/error behavior understood. ## Documentation Requirement For Schema Changes Every endpoint schema change should update: - the endpoint doc under `documentation/endpoints/` - `documentation/operations.md` if a new operation pattern is introduced - `documentation/key-resolution.md` if new state keys or resolver patterns are introduced - `documentation/database.md` if tables or persistence behavior changes - relevant integration docs when external services are involved