Yomizaka
Read before you sign. Drop a lease, a contract, an invoice: Orazaka reads it against the law, examines the PDF for
signs of editing, and shows you every line it relies on. Keep your documents, find any clause again in a second — and
know exactly which run produced each finding.
Yomizaka (読み yomi, reading) is a Krizaka product in development: sign-up is closed, the dev site shows what it does
and a real run. The Dev preview is web only (phone-first); the phone app (apps/mobile, iOS and Android) and the Mac app (apps/desktop) are built beside it and are not part of it.
What it does
- Library — upload PDF, Word (.docx), OpenDocument text (.odt) or plain text files (a queue that pauses, resumes and retries); each is kept as sent, its text
layer read for search (in an isolated worker, after the upload answered 202 Accepted), its SHA-256 recorded; a file sent twice is one document.
- Document verification — a lease read entry by entry against the extraction matrices and technical templates of its jurisdiction
(Québec, France, Wallonia) in force on a date, tools validated by the client's counsel: each finding gives its entry, severity, verdict,
citation and the exact passage, highlighted in the text. Yomizaka verifies documents and screens files; it never verifies an identity.
- Signs of editing — a PDF or office file (.docx, .odt) examined as a file by Orazaka (metadata, dates, revision history): signals at three
plain levels, never a score, never a "fake" stamp.
- Search — every document and every finding, one field (PostgreSQL full text, French and English alike).
- Traced — every analysis is an Orazaka run (the document-validation pack's Studios); its run id is kept and shown.
Yomizaka never calls a model.
- A signed report — a finished check exports a report as HTML and as a signed PDF (a visible signature page, an Ed25519
attestation); only a signed-in member the owner gave access to can verify it (
/app/verifications/report, ADR-0002). A specimen is never signed.
- Who it is for — a « Pour qui ? » picker (tenant, landlord, freelancer, business, other). The tenant and the landlord have
lease rules, the freelancer and the business have the Québec invoice check (8 rules from the federal regulation on input tax credit
information: date, total, GST and QST numbers, taxes, payment terms); contracts say « soon » and promise nothing (
docs/product/direction-2026-10.md). The flows behind them are
data, administered in the database (ADR-0003).
- Checking a tenant's application — a consent-first flow with a provider-agnostic seam; only a demo provider answers, on dev,
with fictitious data. No real provider is contracted yet.
- A short public site — the home (who it is for, one real check recorded, sign-in), sign-in and the privacy notice; nothing else is public (
docs/UX_DECISIONS.md § 9).
- « Forgot your password? » — from the sign-in page: a link mailed through the mail port (the same answer whether or not the address has an account, 3 requests an hour per address), used once, valid for the
auth.passwordResetMinutes setting (30 by default, 5 to 1440, in the administration's General group); it sets the new password and signs every session out. Needs the variables; without them the link is not offered. The audit trail records each request and each reset, never an address, a link or a password.
The administration is admin.yomizaka.com (the same app, routed by host): people, documents, Orazaka runs, flows, operations
and an audit log of every operator action. It answers only addresses of AUTH_ALLOWED_IPS and an administrator's session, and is never indexed.
API
A Pro account can run checks and batches from its own tools with an API key: POST /api/v1/checks, GET /api/v1/checks/{id},
POST /api/v1/batches, GET /api/v1/batches/{id}, described by GET /api/v1/openapi.json — see docs/API.md.
Next
Yomizaka will also check identity documents (photos and scans as well as PDFs) for other Krizaka products that need a
document verified before an account can be opened — served by API, analysed through Orazaka, every finding recorded with
its evidence, and a human decides anything unclear. This is not built yet: it is tracked in
#7.
Start
corepack enable && pnpm install # Node 22, pnpm 10 — also installs the pre-push hook
pre-commit install # once: the gitleaks and zizmor hooks on each commit
cp .env.example .env # a local PostgreSQL URL; AI_API_KEY to run analyses
pnpm dev # http://localhost:3000
pnpm run check # lint · typecheck · tests (what the hook and CI run)
Tests
Unit tests (pnpm test), the page audit (scripts/check-app-pages.mjs) and the page journeys (apps/web/e2e/visual/journeys.visual.mjs, pixels of whole pages as the seeded cast, taken in CI only). To update a baseline run Actions > Update visual baselines on your branch; how the layers work and how to read a diff: krizaka/.github docs/standards/ui-testing.md.
Inside
| Path | |
|---|
apps/web | Next.js 16: the public page, sign-in (@krizaka/ui/auth-layout), the console (AppShell), the BFF (app/api) |
packages/core | zod contracts, query keys, the report readers — shared by the API and the web |
scripts/check-seo-family.mjs | the Krizaka family SEO guard, run in CI on the built site |
scripts/check-overflow.mjs | the responsive crawl (dark and light, 360–1440 px, no console error), run in CI |
scripts/check-app-pages.mjs | the signed-in pages rendered as the seeded persona (E2E_EMAIL, E2E_PASSWORD): exactly one h1, no overflow at 360–1440 px, the header's action on screen, no unnamed button — run in CI after the build (@krizaka/page-audit holds what both crawls measure) |
scripts/check-admin-live.mjs | the walk of the live administration from an allowed address (pnpm run check:admin-live) |
deploy/ | the Docker image and the DigitalOcean App Platform spec (dev.yomizaka.com) |
Demo (the persona Éric) and the phone's Maestro flows
pnpm run demo:seed -- --persona eric [--reset] seeds Éric Tremblay (landlord) with his collections, documents and seeded checks, on dev and local only: it refuses any APP_ENVIRONMENT but dev before it opens a connection (tested). Its login is APP_DEMO_ACCOUNT_EMAIL / APP_DEMO_ACCOUNT_PASSWORD, never typed in the repository; see docs/demo-data.md.
pnpm run dev:seed (demo-seed/cli.mjs --cast) seeds the whole cast of @krizaka/org (krizaka/.github#356): Éric Tremblay with his data set and Mira Haddad (the administrator) and Camille Tremblay, the same three people as the deployed QA accounts. It is the one seed of local, CI (ci-after-build.sh, ci-mobile-backend.sh), Maestro and the recorders; --check compares the result to scripts/demo-seed/fingerprint.json (counts per table), so a dev database and a laptop hold the same data. apps/web/scripts/qa-accounts.mjs gives the QA accounts the same persona names. Names live in the cast only (scripts/cast-drift.test.mjs guards it); e-mails and passwords come from the environment.
- Reproduce a hot fix locally:
export LOCAL_DB_PASSWORD=$(openssl rand -hex 12), docker compose -f deploy/docker/compose.yml up -d, then export DATABASE_URL=postgres://yomizaka:$LOCAL_DB_PASSWORD@localhost:5432/yomizaka, pnpm run dev:seed (on this machine the cast signs in with [email protected] / [email protected], password local-cast-password-0123), pnpm dev, sign in as Éric.
apps/mobile/.maestro/ holds the flows, which sign in through shared/sign-in.yaml with PERSONA_EMAIL / PERSONA_PASSWORD. smoke and tabs (a capture per tab: Accueil, Vérifications, Lots) are tagged ci; check-document runs a paid engine check through the system picker and is tagged manual.
- In CI, every pull request runs them on an Android emulator (
mobile-ci.yml → the org's mobile-e2e.yml, krizaka/.github#241): scripts/ci-mobile-backend.sh starts a throwaway PostgreSQL and the built web app and seeds Éric with a password made for the run, so the demo data is reset each time and no shared account is used. The check is mobile-e2e / gate; the screenshots, the screen recording and the JUnit report are the artifact of the run, which is where a PR's phone captures come from.
Environment
Every variable is declared once in apps/web/lib/env.ts (see .env.example); a test keeps this table in sync.
| Variable | Meaning |
|---|
APP_ENVIRONMENT | dev or prod: which flows are enabled |
APP_PUBLIC_URL | the public address (www.yomizaka.com: canonical links, indexed) |
APP_DEMO_ACCOUNT_EMAIL, APP_DEMO_ACCOUNT_PASSWORD | optional credentials for the dev/local demo persona seed |
APP_DEV_HOST | the development address (dev.yomizaka.com): pages go to www with a 308, the API and /.well-known keep serving, noindex |
APP_IOS_TEAM_ID | the Apple team that signs the iOS app: /.well-known/apple-app-site-association (universal links; 404 while unset) |
APP_ANDROID_CERT_SHA256 | the SHA-256 fingerprint(s) of the Android app's signing certificate: /.well-known/assetlinks.json (404 while unset) |
APP_VISUAL_NOW | an ISO instant: the date the console writes as « today » in the visual runs (dev only; refused in production) |
APP_SEARCH_INDEXING | on or off: off answers noindex everywhere |
APP_REPORT_SIGNING_KEY | the Ed25519 key that signs reports |
DATABASE_URL, DATABASE_CA_CERT | PostgreSQL (in production the PgBouncer pool pool-yomizaka) and its CA |
DATABASE_DIRECT_URL | the database reached directly: migrations and session advisory locks need one backend; unset, DATABASE_URL |
DATABASE_MAX_CONNECTIONS | the size of the connection pool (default 5) |
AUTH_SESSION_SECRET |
Rules for contributors and agents: AGENTS.md. Security: SECURITY.md.
License
FSL-1.1-ALv2 (Functional Source License, Apache-2.0 future licence) © Technologies Krizaka Inc. — read,
run, modify and self-host it for any purpose except offering a competing service; each version becomes Apache-2.0 two
years after its release. Commits before the licence change remain Apache-2.0 — see NOTICE
and ADR-012.
The Krizaka names and birds are not licensed: trademark policy.