Credora

Pre-approved corporate loan offers for Sapphire Bank, decided inside Exasol.

Built for ExaThon India 2026 · Powered by Exasol Personal.

Site Address
Live app https://credora.loan
Docs https://docs.credora.loan
Demo video https://video.credora.loan
Presentation https://ppt.credora.loan
Outside world (mock CIBIL, GSTN, Account Aggregator) https://credora.link

Sign in with one click on the login page, or use these demo logins. All data is synthetic, so the passwords are public on purpose.

Role Login What to try
Admin admin / Demo@123 Generate a fresh data set, watch the seven sources, run the analysis
Data scientist datasci / Demo@123 Train a risk model inside Exasol, compare versions, run what-if on policy
Loan operations loanops / Demo@123 Open any company's Exasol report: the decision, why, and every step Exasol ran
Relationship manager rm / Demo@123 Negotiate a pre-approved offer inside the limit Exasol computed. Signs in as Subhashree Mohanty (RM001) and sees only her book

Every role also has Ask Credora: plain-English questions answered by Claude through the official Exasol MCP server, logged in to Exasol as that role's own database user.

Verify it yourself#

Each claim can be checked on the live site and in one or two files.

Claim Check on https://credora.loan Code that proves it
The whole analysis is one Exasol call Sign in as loanops, open Analysis runs, press Run analysis, then open any company's report: 11 steps, each with its SQL, Lua or Python and its time (about 20–22 s for 1,000 companies) exasol/lua/06_run_analysis.sql (RUN_ANALYSIS; step 11 is the PREFERRING skyline)
Bank data is read in place, never copied Sign in as admin, open Sources: Oracle, MySQL and PostgreSQL tables are counted through VS_CBS, VS_CIF and VS_LOS exasol/sql/03_virtual_schemas.sql
Exasol fetches outside data over the internet Visit https://credora.link: the CIBIL, GSTN and Account Aggregator relays that Exasol's UDFs call exasol/udf/04_api_udfs.sql, exasol/sql/02_connections.sql
The model is trained and scored inside Exasol Sign in as datasci, open Risk models, press Train new model (AUC about 0.75) exasol/udf/05_ml_udfs.sql
Each role reads through its own Exasol user Sign in as rm: PAN and GSTIN are masked and no outside data appears, because CREDORA_RM has no grant on it exasol/sql/07_security.sql, backend/app/exa.py ROLE_USER, backend/app/routes/core.py db()
Ask Credora is bound by the same grants Ask the first admin question below as admin, then as rm: the admin's SQL joins VS_CIF, VS_LOS and VS_CBS across three databases; the RM's stays on V_COMPANY_MASKED. Every answer shows each SQL statement it ran, and the API response names the Exasol user backend/app/assistant.py exasol_login(), MCP_SETTINGS, _on_topic()
Metrics are certified in a semantic layer Ask "Which 5 industries have the highest pre-approved amount, with their approval rate?": the SQL reads CREDORA_SEM.PORTFOLIO exasol/semantic/12_credora_model.sql, exasol/extensions/10_semantic_views_module.sql
Credit memos are written inside Exasol Open a company report and press Credit memo: the engine shown is exasol-udf exasol/udf/09_ai_udf.sql, backend/app/memo.py
Outside data is purged with proof Sign in as admin, open Audit and purge: row counts and SHA-256 fingerprints exasol/lua/08_purge.sql
Everything rebuilds from this repo One command in any AWS account deploy/credora.py, deploy/exasol_setup.py, infra/main.tf

Contents#

  1. The problem
  2. How Credora solves it
  3. Architecture
  4. Exasol at the centre
  5. Role-based access, enforced by Exasol
  6. Ask Credora: try these
  7. Scale and measured performance
  8. Key decisions and trade-offs
  9. Security and data governance
  10. Failure modes
  11. Deploy it yourself
  12. Repository layout
  13. Documentation

1. The problem#

Sapphire Bank has 1,000 corporate current-account customers, each run by 2 to 5 partners. Instead of waiting for loan applications, the bank wants to approach its best customers with a pre-approved loan offer: an amount, a rate (ROI) and a tenure, plus a negotiation limit the relationship manager can move within without going back to credit.

To decide that, a credit officer needs data that lives in six places, half inside the bank and half outside it:

Data Where it lives Owner
Accounts and about 8.5 lakh current-account transactions Oracle core banking Sapphire Bank
Companies, partners, KYC MySQL customer master Sapphire Bank
Each company's credit need on file, 5,000 past loans with outcomes PostgreSQL loan origination and CRM Sapphire Bank
Credit reports for every partner and company CIBIL Outside party
2 to 10 years of monthly GST returns GSTN Outside party
Partners' accounts at other banks, with consent Account Aggregator Outside party

Requirements

  • Functional: combine all six sources per company; score credit risk with a model trained on the bank's own loan history; price an offer and a negotiation limit that still meet the bank's return hurdle; rank the portfolio; show every number with its source; let four roles work the result, from data generation to sanction.
  • Non-functional: no copy of core banking leaves the bank's databases; consent-based outside data is deleted on time, with proof; each role sees only what it may see, enforced by the database; the full analysis of 1,000 companies runs in under a minute; the whole system rebuilds in any AWS account from this repo with one command.
  • Out of scope: real CIBIL, GSTN or Account Aggregator connections (Credora ships faithful mocks); loan disbursement and servicing; real customer data of any kind.

2. How Credora solves it#

One call, EXECUTE SCRIPT CREDORA.RUN_ANALYSIS('<run>'), does the whole job inside Exasol in about 20 seconds:

  1. Read the bank's data in place. Virtual schemas expose Oracle, MySQL and PostgreSQL as Exasol schemas. Queries are pushed down to the source; nothing is copied first.
  2. Fetch the outside world. Python UDFs call the CIBIL, GSTN and Account Aggregator relays over the public internet, 16 in parallel, and stage the replies with a purge time.
  3. Build features. Thirteen credit features per company: GST turnover and filing discipline, the gap between GST turnover and bank credits, balances, inflow volatility, bounces, CIBIL ranks and partner scores, other-bank balances, debt service cover.
  4. Score risk. A gradient-boosted model, trained inside Exasol on the bank's past loans, gives each company a probability of default and the effect of each feature on it.
  5. Price and decide. Amount, ROI and tenure as the offer; floor ROI, maximum amount and maximum tenure as the negotiation limit, where the bank's risk-adjusted return (RAROC) still meets its hurdle; Approve, Refer or Decline with reasons.
  6. Rank. Exasol's PREFERRING skyline peels off the companies that are best on return, risk and size at the same time. The top 50 go to the relationship managers.
  7. Hand over. The web app exports the offers to the CRM, and relationship managers negotiate inside the limit while loan operations verifies and sanctions.

Every step is logged with its row count and duration, and the web app shows each one with the SQL, Lua or Python that ran.

3. Architecture#

Diagrams: all diagrams · big picture · AWS deployment · inside Exasol · analysis flow · roles and AI access · full design document

   Sapphire Bank (private RDS)                    Outside world (https://credora.link)
   Oracle CBS   MySQL CIF   PostgreSQL LOS        cibil.   gst.   aa.   (HTTPS relays)
      |             |             |                  |       |      |
  Oracle VS    adbc-vs-rs    adbc-vs-rs          Python SET UDFs, 16 in parallel
      \_____________|_____________/__________________|_______|______|
                                  |
               Exasol Personal on EC2 (r6i.xlarge, via the official launcher)
   virtual schemas · API UDFs · ML training and scoring · Lua orchestration · PREFERRING
   per-role users · masking · purge with proof · preprocessor framework · semantic layer
                                  |
          Web app at https://credora.loan (React + FastAPI behind Caddy, HTTPS)
     Admin · Data scientist · Loan operations · Relationship manager · Ask Credora (MCP)
       each role reads Exasol as its own user: CREDORA_ADMIN / _DATASCI / _LOANOPS / _RM
Component Technology Why it is there
Analytics platform Exasol Personal 2026.1 on EC2, installed by the official launcher The single place where bank and outside data meet and become a decision
Bank databases RDS for Oracle SE2, MySQL 8.4, PostgreSQL 16 in private subnets Stand in for a bank's real core banking, customer master and loan origination systems
Outside parties Mock CIBIL, GSTN and Account Aggregator APIs (FastAPI, own database each), published as cibil., gst., aa.credora.link Faithful stand-ins for external services that Exasol reaches over the internet
Data generator Python service behind the admin's "Generate mock data" button Rebuilds a consistent synthetic world (1,000 companies, ~3,500 partners) on demand, or adds more companies to it (append mode keeps every company name, partner name, PAN, GSTIN and account number unique)
Web app React + TypeScript (Vite), FastAPI, Caddy with automatic HTTPS Four role-based workspaces; every number tagged with its source
AI Claude (claude-sonnet-5-5) via the Anthropic API, or Amazon Bedrock with AI_PROVIDER=bedrock; the official Exasol MCP server (exasol-mcp-server 2.3.0, writes off); a CREDIT_MEMO UDF Ask Credora answers plain-English questions as the signed-in role's Exasol user, semantic layer first, showing every SQL it ran; credit memos are written inside Exasol
Infrastructure OpenTofu (in Docker), Route 53 for both domains, Secrets Manager, S3, IAM Reproducible from the repo in any AWS account

4. Exasol at the centre#

Credora is assembled from Exasol's open-source building blocks, from the exasol and exasol-labs GitHub organisations, plus the bank-specific logic in this repo. docs/WHY_EXASOL.md covers each feature in depth.

Exasol feature Used for Code
Virtual schemas: Oracle VS 6.0 (Java) and adbc-vs-rs 0.7 (Rust, ADBC, Arrow) Read Oracle, MySQL and PostgreSQL in place exasol/sql/03_virtual_schemas.sql
Custom script language container (Rust 0.23.1) and BucketFS Run the Rust adapter; hold drivers and model files deploy/exasol_setup.py
Python UDFs (SET scripts) and CONNECTION objects Call the outside APIs in parallel, credentials kept out of SQL exasol/udf/04_api_udfs.sql
ML in UDFs Train (TRAIN_PD) and score (PD_SCORE) a monotonic gradient-boosted model, versioned in BucketFS exasol/udf/05_ml_udfs.sql
Lua scripting RUN_ANALYSIS, TRAIN_MODEL, PURGE_EXPIRED exasol/lua/
Analytic SQL and PREFERRING Feature engineering; multi-criteria skyline ranking exasol/lua/06_run_analysis.sql
Roles, users, grants, masked views Each app role reads through its own Exasol user; jobs run as CREDORA_SVC exasol/sql/07_security.sql
preprocessor-framework 0.9.1 Owns Exasol's single preprocessor slot and dispatches per role, fail-open exasol/extensions/
exasol-semantic-views 0.5.1 CREDORA_SEM.PORTFOLIO: 15 certified portfolio metrics exasol/semantic/
Exasol MCP server 2.3.0 Ask Credora: Claude queries Exasol as the signed-in role's own Exasol user, so the same grants bound the AI; writes switched off backend/app/assistant.py
Generative AI in a UDF CREDORA.CREDIT_MEMO calls Claude through CONNECTION AI_LLM and returns the memo as SQL output exasol/udf/09_ai_udf.sql
Purge with proof (Lua) PURGE_EXPIRED deletes consent-based outside data on time, keeping row counts and SHA-256 fingerprints exasol/lua/08_purge.sql
Exasol Personal launcher One-command installation on AWS, ports limited to admin IPs deploy/credora.py

5. Role-based access, enforced by Exasol#

Access is decided by Exasol, not by the web app. Each of the four roles has its own Exasol user and database role (exasol/sql/07_security.sql). The backend runs every read for a signed-in person as that person's role user (backend/app/exa.py ROLE_USER, backend/app/routes/core.py db()); a query Exasol refuses comes back as 403 Exasol denied access for your role. Ask Credora starts the Exasol MCP server logged in as the same user (backend/app/assistant.py exasol_login()), so the AI can read exactly what the person can read, no more. Analysis, training, the CRM export and the purge run as the service user CREDORA_SVC.

Diagram: roles and AI access shows the four roles as rings of data, one Ask Credora question travelling from the login token through the topic gate and exasol_login() into Exasol as the role's own user, and what each role and its AI can and cannot do.

App role (login) Exasol user / role What the app shows What Ask Credora can read
Admin (admin) CREDORA_ADMIN / R_ADMIN Data generation, sources, audit and purge, analysis runs, decisions, Top 50, risk models, offer pipeline Results (CREDORA), the semantic view CREDORA_SEM.PORTFOLIO, the bank's databases through VS_CBS (Oracle), VS_CIF (MySQL) and VS_LOS (PostgreSQL), and raw outside data in CREDORA_STAGE
Data scientist (datasci) CREDORA_DATASCI / R_DATASCI Risk models (train, activate), what-if on policy, analysis runs, decisions, sources Same as admin
Loan operations (loanops) CREDORA_LOANOPS / R_LOANOPS Run analysis, every company report, approval queue (verify, sanction, reject) Results, the semantic view and the three bank databases; not raw outside data (CREDORA_STAGE)
Relationship manager (rm) CREDORA_RM / R_RM Own book only (RM001), masked PAN and GSTIN, my pipeline, negotiation inside the limit, Top 50 The semantic view, DECISIONS, SCORES, CONFIG, RUN_LOG and the masked company view V_COMPANY_MASKED only; no features, no bank databases, no outside data
(fallback) CREDORA_MCP / R_MCP Not a login Read-only results; used by Ask Credora only when a role user's password is not configured

How the layers fit:

  • Objects and columns are decided by Exasol grants. The latest-run views behind the semantic layer run with their owner's rights and are granted per role (exasol/semantic/11_latest_run_views.sql), so the RM's semantic queries never touch model features.
  • Semantic SQL is routed per role by the preprocessor framework: one rule per role in exasol/extensions/10_semantic_views_module.sql. CREDORA_SVC has no rule and pays nothing.
  • The RM's book (rows where RM_ID = 'RM001') is filtered by the backend on top of the CREDORA_RM grants.
  • The AI cannot write. The MCP server runs with enable_write_query, enable_write_bucketfs and the preprocessor tools switched off (MCP_SETTINGS in backend/app/assistant.py).

Verified on the live site: an admin question joined VS_CIF."partner", VS_LOS."application" and VS_CBS.TXN / ACCOUNT across three databases in one statement; the same question asked as the RM was answered from V_COMPANY_MASKED only.

6. Ask Credora: try these#

Ask Credora answers from the semantic layer CREDORA_SEM.PORTFOLIO first (15 certified metrics, exasol/semantic/12_credora_model.sql), then with plain SQL where the role allows it. Each answer lists every MCP tool call with the exact SQL it ran. A one-word topic check runs before any tool use: unrelated requests (poems, recipes, "ignore your rules") are refused and never reach Exasol.

The page suggests four questions per role, each exercising a different Exasol feature:

Role Question Exercises
Admin For company C000229, join its partners from the customer master, its credit need on file and its current-account credits over the last 12 months from core banking. Cross-database join: MySQL VS_CIF + PostgreSQL VS_LOS + Oracle VS_CBS
Admin Which 5 industries have the highest pre-approved amount, with their approval rate? Semantic view
Admin How long did each step of the latest analysis run take, and how many rows did it process? RUN_LOG
Admin Which partners have a CIBIL score below 650, and which companies are they partners in? Raw CIBIL stage (CREDORA_STAGE) joined with the MySQL customer master
Data scientist Compare the risk model versions: AUC, Gini and the top three features of each. MODEL_REGISTRY
Data scientist What are the average probability of default and the expected loss by GST stage and grade? Semantic view
Data scientist Do companies with a bigger gap between GST turnover and bank credits get worse grades? FEATURES
Data scientist From the past loans in loan origination, what is the default rate by CIBIL commercial rank? PostgreSQL through VS_LOS
Loan operations Which approved companies have their KYC expired or pending in the customer master? MySQL VS_CIF joined with DECISIONS
Loan operations Show the 5 referred companies with the largest indicated need, and why each was referred. DECISIONS (hard fails) and SCORES
Loan operations For the top 10 ranked companies, what were their current-account credits over the last 12 months in core banking? Oracle VS_CBS joined with DECISIONS
Loan operations How many companies were declined for each hard-fail reason? DECISIONS
Relationship manager Which of my companies have the most negotiation headroom? Semantic view
Relationship manager What is the lowest ROI I can offer my top-ranked company, and what is the RAROC at that rate? DECISIONS (floor ROI, RAROC at the floor)
Relationship manager What are my book's approval rate and pre-approved amount by industry? Semantic view
Relationship manager Which top-50 companies are in my book? DECISIONS

Ask a question outside a role's grants (for example the admin's cross-database question as rm) to see Exasol, not the prompt, set the limit.

7. Scale and measured performance#

The demo data set is generated, but its volumes are realistic for a mid-size corporate book.

Data Volume
Companies / partners 1,000 / ~3,500
Current-account transactions (Oracle) ~850,000
GST returns (via the GSTN relay) ~71,000
Credit reports (via the CIBIL relay) ~3,500 consumer + 1,000 commercial
Other-bank accounts (via the AA relay) ~6,000 accounts, ~400,000 transactions
Past loans for training 5,000, ~8% defaulted

RUN_ANALYSIS on the live deployment (one r6i.xlarge node):

Step Rows Time
Refresh three virtual schemas 3 ~1.7 s
Read credit needs and customer master (PostgreSQL + MySQL) 1,000 ~0.3 s
CIBIL consumer and commercial reports (public relay) 4,490 ~1.2 s
GST returns (public relay) ~71,000 ~1.5 s
Account Aggregator (public relay) ~5,800 ~3.4 s
Features over Oracle transactions (pushdown aggregation) 1,000 ~10.5 s
Probability of default (ML UDF) 1,000 ~1.9 s
Decide offer and negotiation limit 1,000 <0.1 s
Rank with PREFERRING top 50 <0.1 s
Total ~20–22 s

The risk model reaches an AUC of about 0.75 on a hold-out set of past loans. A full data regeneration takes about 75 seconds.

8. Key decisions and trade-offs#

Decision Solves Worsens Would change when
Read the bank's databases through virtual schemas instead of loading them No copy of core banking; always current; one SQL surface over three engines Each run pays network and source-database cost; features depend on the sources being up Runs need to be much faster or more frequent: materialise the monthly aggregates in Exasol on a schedule
Call outside parties from UDFs over public HTTPS relays External data lands next to bank data in one SQL step; mirrors how real bureaus are reached Internet latency and a public endpoint to protect (API key, rate limits) A real bureau requires private connectivity: point the CONNECTION objects at a private endpoint, no code change
Train and score the model inside Exasol No data export to an ML platform; versioned models in BucketFS; scoring is a SQL step Limited to libraries in the Python container; no GPU Models need deep learning or heavy feature stores: score externally and keep only results in Exasol
Rank with PREFERRING instead of a weighted score No hand-tuned weights; shows the genuinely non-dominated companies Skyline layers are harder to explain than one number The bank wants one policy-driven score: keep the skyline for exploration, add a weighted rank
One Exasol user per app role, also for the AI Access is enforced by the database even if the app or the prompt has a bug; Ask Credora cannot read more than the person asking; audit shows the real role More users and grants to manage; one MCP server process per question Hundreds of roles: move to impersonation or an identity provider
Preprocessor framework + semantic views Many SQL extensions share Exasol's single preprocessor slot safely; certified metrics for humans and AI Adds a step on every statement for the routed roles (~4 ms) Statement latency matters more than governed metrics for a role: remove its routing rule
Single Exasol node and one app host Cheap, simple, fits the hackathon No high availability; a host failure is an outage Production: multi-node Exasol, two app hosts behind a load balancer, Multi-AZ RDS
Mock outside parties with their own databases Realistic, repeatable demos with consistent hidden risk Not real-world data quality Real integrations: replace the relays' targets, keep the UDFs and contracts

9. Security and data governance#

  • Network: only Caddy (80, 443) is public. Exasol's ports (8563, 8443, 2581, 22) open only to admin IPs; the RDS databases sit in private subnets reachable from the VPC only.
  • Least privilege in the database: each role reads as its own Exasol user (section 5). Loan operations cannot read raw outside data; relationship managers read results and a masked company view, and the app limits them to their own book.
  • AI inside the same boundary: Ask Credora's MCP server logs in as the signed-in role's Exasol user with writes switched off; a topic check refuses unrelated questions before any query; every SQL statement it ran is shown with the answer. Credit memos are generated inside Exasol by the CREDIT_MEMO UDF, with the API key held in CONNECTION AI_LLM.
  • Secrets: generated per deployment by OpenTofu into AWS Secrets Manager; Exasol keeps API tokens in CONNECTION objects; nothing secret is in the repo.
  • Consent and retention: raw CIBIL, GST and Account Aggregator replies carry a purge time. PURGE_EXPIRED deletes them on schedule and keeps the row count and a SHA-256 fingerprint as proof.
  • Synthetic data only: every company, person and account is generated.

10. Failure modes#

If this fails What happens Recovery
A bank database (RDS) The analysis step that reads it fails and is logged; the previous run's results stay visible in the app Re-run the analysis when the source is back
An outside relay The fetch step fails with the API's error; no partial run is published Re-run; the relays are stateless
A broken preprocessor module The framework skips it (fail-open), so ordinary SQL keeps working Fix or remove the module's rule
The Exasol node The app shows the last results it can reach; analysis and AI are unavailable Restart through the launcher; all objects are recreated idempotently by deploy
The app host The site is down; Exasol and the databases are unaffected python deploy/credora.py ship --env <name> rebuilds it
The AI provider Ask Credora and memos show "not configured" or an error; everything else works None needed; or switch provider with AI_PROVIDER=bedrock
The Exasol MCP server Ask Credora returns 503 ("could not start"); the rest of the app is unaffected Ask again; each question starts a fresh server process
A question outside the AI's grants Exasol refuses the query; Claude says the role cannot see that data None: this is the access control working

11. Deploy it yourself#

You need an AWS account with one Route 53 hosted zone (two for the outside-world domain), the AWS CLI logged in, Docker, Node.js, Python 3.12 and the Exasol Personal launcher.

bash
cp .env.example .env.mysite      # AWS_PROFILE, DOMAIN, optionally EXTERNAL_DOMAIN
make setup                       # Python dependencies for the deploy tool
make deploy ENV=mysite           # or: python deploy/credora.py deploy --env mysite

deploy is idempotent and builds everything in order:

  1. Exasol Personal on EC2 through the official launcher, its ports limited to your IP.
  2. RDS for Oracle, MySQL and PostgreSQL, the app host, S3, Secrets Manager and DNS for both domains, with OpenTofu.
  3. The web app, API, mock APIs, generator, docs, video and presentation sites, with Docker Compose.
  4. 1,000 companies of synthetic data.
  5. In Exasol: the Rust container, both virtual schema adapters, the Oracle JDBC driver, connections, UDFs, Lua scripts, virtual schemas, roles, users, the preprocessor framework and the semantic model.
  6. The first model training and analysis.
Command Does
python deploy/credora.py status --env <name> Site address, logins, container health
python deploy/credora.py access --env <name> Writes deployments/<name>/ACCESS.md: every URL, login, password and connection command
python deploy/credora.py allow-ip --env <name> Opens Exasol and SSH to another machine's IP
python deploy/credora.py ship --env <name> Rebuilds and restarts the app host only
python deploy/credora.py exasol --env <name> Re-applies the Exasol objects only (containers, adapters, UDFs, Lua, roles and users, preprocessor, semantic model)
python deploy/credora.py generate --env <name> Regenerates the synthetic data
python deploy/credora.py destroy --env <name> Removes everything the deployment created

Everything local about a deployment (launcher directory, OpenTofu state, SSH keys, logs, ACCESS.md) lives in deployments/<name>/, which is gitignored. Copy it with .env.<name> to operate the same deployment from another machine. See docs/PORTING.md.

12. Repository layout#

credora/
├─ deploy/        one-command deploy tool, remote start script
├─ infra/         OpenTofu: RDS x3, app host, S3, secrets, Route 53 for both domains
├─ exasol/
│  ├─ sql/        schemas, connections, virtual schemas, security
│  ├─ udf/        Python UDFs: outside APIs, ML training and scoring, AI memo
│  ├─ lua/        RUN_ANALYSIS, TRAIN_MODEL, PURGE_EXPIRED
│  ├─ extensions/ the semantic layer as a preprocessor-framework module
│  └─ semantic/   latest-run views and the Credora semantic model
├─ db/            Sapphire Bank schemas (Oracle, MySQL, PostgreSQL) and the mock API schemas
├─ mocks/         mock CIBIL, GSTN and Account Aggregator APIs; synthetic data generator
├─ backend/       FastAPI: roles, jobs, reports, CRM export, Ask Credora
├─ frontend/      React + TypeScript
├─ sites/         docs, video, presentation and outside-world sites
├─ media/         demo video and presentation files
└─ docs/          architecture, diagrams, data model, APIs, why Exasol, porting

13. Documentation#

Document Covers
docs/architecture.html The full design: components, roles, data, decision logic, deployment
docs/diagrams/ Big picture, AWS deployment, inside Exasol, analysis flow
docs/WHY_EXASOL.md Every Exasol feature and building block used, and why
docs/DATA_MODEL.md Bank schemas, mock API data, feature definitions
docs/API.md Mock API contracts and the web app's API, including Ask Credora's response and topic check
docs/PORTING.md Deploying to another AWS account or domain

License#

MIT. See LICENSE.