Changelog
Release history for PII Firewall SDK, MCP Server, and REST API.
Unreleased (targeting v0.2.0 — 2026-05-01)
🟡 Changed (Session 172 — app.piifirewall.com public-facing terminology cleanup)
app/index.html: meta description updated (publicly visible in Google search snippets)app/src/Login.jsx: login screen badge text updated (visible to all unauthenticated visitors)- ⚠️ Requires manual deploy via
npm run build --workspace=@pii-firewall/app
🟡 Changed (Session 172 — Blog article withdrawn)
landing/blog.html: Removed the article card from the blog indexlanding/blog/himitsu-bunsan.html: File deletedlanding/_redirects: Added Cloudflare 301 permanent redirects from/blog/himitsu-bunsanand/blog/himitsu-bunsan.htmlto/blog
🟡 Changed (Session 172 — Crawl blocking for not-yet-public landing pages)
landing/portal.html/blog.html/index-v2.html/docs.html: Implemented 3-layer crawl blocking (HTML metanoindex,nofollow,noarchive,nosnippet,noimageindex+_headersX-Robots-Tag+ newlanding/robots.txtDisallow). To be removed page-by-page per the procedure ininternal-docs/infra/pre-production-checklist.md§H-Y when each page is ready for public release.landing/robots.txt: Added explicit User-agent blocks for major AI training crawlers (GPTBot / ClaudeBot / anthropic-ai / Google-Extended / PerplexityBot / Bytespider / CCBot / Meta-ExternalAgent / Applebot-Extended and 15+ others). Ensures bots that respect only their own name string are blocked even when a wildcard is set.
🟡 Changed (Session 172 — Landing page terminology cleanup)
landing/index.html: Unified technical wording to "Cryptography" / "暗号技術" (13 occurrences). The Privacy-by-Design / zero-knowledge messaging is preserved.
🔴 Breaking (Session 172 — Admin Phase 3-A RBAC + Supabase Auth full migration)
ADMIN_SECRETfully retired: The admin panel and all 9/admin/*proxy endpoints have migrated from the legacyADMIN_SECRETBearer auth to Supabase Auth + admin_users RBAC. After deployment theADMIN_SECRETRailway variable is no longer required (manual deletion recommended)- MFA (TOTP) mandatory: Admin panel login now requires Email OTP + TOTP MFA (AAL=aal2)
🟢 Added (Session 172 — Admin Phase 3-A RBAC)
proxy/migrations/004_admin_users.sql(new):admin_userstable (email PK / role CHECK 3 values / active / created+updated audit columns / note) +idx_admin_users_activepartial index +updated_attrigger + initial adminkmishimasl@gmail.comproxy/index.js: NewrequireAdminRole(allowedRoles)middleware (JWT verification → AAL=aal2 check → admin_users lookup → role check). New/admin/me,/admin/usersCRUD endpoints (GET/POST/PATCH/DELETE). All 9 existing admin endpoints rewritten to use the middleware. Alert ACK/Resolveoperatoridentifier now uses the authenticated email (replacing the Phase 2-A'admin'constant)admin/src/lib/supabase.js(new): Supabase client initialization +getAccessToken/getAuthHeader/getAuthState/hasTotpFactor/signOuthelpersadmin/src/Login.jsx(new, ~380 lines): 4-state consolidated login screen (email → OTP → mfa_challenge → mfa_enroll). Ported fromlanding/console.htmlOTP + MFA logic (90% reuse) and React-ifiedadmin/src/App.jsx: Fully removed ADMIN_SECRET auth. AddedauthedFetchwrapper,refreshAuthStateorchestrator,can(action)RBAC helper. 5-state authState gating (loading / unauthenticated / mfa_required / mfa_enroll / authenticated / forbidden). Topbar role badge (🛡️/🔧/👁️ + email) + sign-out button. RBAC guards (disabled + tooltip) on Alert ACK/Resolve, Credit Grant, Set Plan, and API key Revoke buttonsadmin/src/App.jsx: Added "🛡️ Admin User Management" section to the Policy tab (admin role only: add / role change / active toggle / delete; protected against demoting/deleting the last active admin)admin/src/i18n/ja.json・en.json: ~50 new keys (login.email.*,login.otp.*,login.busy.*,login.error.*,mfa.challenge.*,mfa.enroll.*,mfa.error.*,auth.*,role.*,rbac.error.*,rbac.users.*)
🟢 Added (Session 171 — Admin Phase 2-C CSV Export)
admin/src/lib/csv-export.js(new, ~90 lines):toCsv(rows, columns)+downloadCsv(baseName, rows, columns)utilities. RFC 4180 compliant, UTF-8 BOM prepended (for direct Excel JA import), arrays/objects JSON-stringified, null/undefined empty-stringifiedadmin/src/App.jsx: Added📊 CSVbutton to 6 tables (Logs / Alerts / Users / Customers / PII Analysis / Credits). All exports reflect Phase 2-B filter stateadmin/src/App.jsx: Chose self-implementation overpapaparse(8.7KB bundle increase vs. 45KB for papaparse)admin/src/App.jsx: ⚠️ P15 compliance — exports contain only aggregates, metadata, and masked tokens. No raw PII (not present in DB)admin/src/App.jsx: Auto timestamp in filename (e.g.,logs_2026-05-14_1830.csv)admin/src/i18n/ja.json・en.json: 36 keys added (csv.button,csv.tooltip,csv.empty+ 33 column headers)
🟢 Added (Session 171 — Admin Phase 2-B Date Range & Search Filter)
admin/src/App.jsx: IntegrateduseFilter-equivalent state. Presets (Today / 7d / 30d / 90d / All / Custom) + native<input type="date">(Custom only) + search box. No new packages required (chose native HTML overreact-day-picker)admin/src/App.jsx: Filter state synced to URL query params (?preset=7d&from=...&to=...&q=...). Bookmark and shared URL reproduce filter stateadmin/src/App.jsx:renderFilterBar()helper shared across 4 tabs (Logs / Alerts / Users / Customers). matchedCount always shown on the rightadmin/src/App.jsx: Filter applied to Logs (timestamp + email/endpoint/ai_service search), Alerts (created_at + alert_type/email/description search, combined with status filter), Users (filtered to users with logs in range), Customers (lastActive + email search)admin/src/i18n/ja.json・en.json: 14 keys added (filter.range,filter.preset.*,filter.from/to/search/clear/matched/empty,filter.searchPlaceholder)
🟢 Added (Session 171 — Admin Phase 2-A Alert ACK/Resolve Workflow)
proxy/migrations/003_alerts_ack_resolve.sql(new): Added 6 columns toalertstable (status/acknowledged_at/acknowledged_by/resolved_at/resolved_by/resolution_note). CHECK constraint limits status to 3 values (open/acknowledged/resolved). Addedidx_alerts_statusindex +idx_alerts_status_openpartial index. Backward compatible: existing rows automatically initialized tostatus='open'proxy/index.js: Added 2 endpointsPATCH /admin/alerts/:id/ackandPATCH /admin/alerts/:id/resolve. Resolve can be invoked directly without prior ACK (auto-fillsacknowledged_*for audit integrity).resolution_notetruncated at 1000 chars (DoS protection). BearerADMIN_SECRETauthadmin/src/App.jsx: Alert workflow UI — status badges (🔴 Open / 🟡 Acknowledged / 🟢 Resolved), status filter tabs (All / Open / Acknowledged / Resolved), ACK button, Resolve modal (resolution note, 1000 char limit), post-resolve display of operator / timestamp / note. Default filter is "Open"admin/src/App.jsx: Topbar open-critical badge (clicking jumps to Alerts tab "Open" filter). Dashboard "Critical Alerts" stat card now usesopenCriticalCount(consistent with "Unresolved" subtitle)admin/src/i18n/ja.json・en.json: 24 keys added (alert.status.*,alert.filter.*,alert.action.*,alert.meta.*,alert.modal.*,alert.error.*,alert.empty.filtered,badge.openCritical)
🟡 Changed (Session 170 — Topbar color follow-up)
admin/src/App.jsx:.badge-redchanged from--accent2harsh red to--warnamber (unifies "100 critical alerts" topbar badge and CRITICAL badge inside alert cards)admin/src/App.jsx:.btn-pdf(Export PDF button) changed from--accent2red to calm slate-blue. Supports both dark/light modes
⚪ Docs (Session 170 wrap)
- Session 170 handoff and session report created (
Session/PIIFirewall_session_2026-05-14_Session170.md+Session/handoff_2026-05-14_Session170.md) internal-docs/project/sprint.mdupdated (Session 170 block added, Session 168 moved to backlog, next TODO updated for Session 171)memory/project_progress.mdupdated (admin completeness 75%→85%)
🟢 Added (Session 170 — Admin Phase 1-B Chart.js & dark/light theme)
admin/: Implemented dark/light theme toggle (☀/🌙 button in Topbar, persists vialocalStorage.admin_theme, initial detection viaprefers-color-scheme)admin/src/lib/chart-theme.js(new): Chart.js theme integration (cssVar()helper,getChartPalette(),applyChartDefaults(), auto re-render ondata-themeattribute change)admin/src/components/charts/(new):LineChart/BarChart/PieChart/DonutChartwrapper components- Dashboard tab: Added daily-trend LineChart (last 14 days, 2 series: requests / PII detections), replaced CSS bar graph for AI service usage with horizontal BarChart
- PII Analysis tab: Type breakdown BarChart (horizontal, danger color, auto-expanding height) + Category DonutChart (5 categories, total count in center) in 2-column layout. Added
PII_CATEGORY_MAP(16 types → 5 categories) - Alerts tab: Severity-based PieChart (critical / high / info) + large-number summary card (3 columns, color-coded to match)
- Users tab: User ranking horizontal BarChart (Top 10, 2 series: requests / PII detections)
- Logs tab: Hourly usage BarChart (24 hours, off-hours highlighted in danger color) + large-number off-hours summary card. Defines 7:00–22:00 as business hours for shadow usage detection
- BarChart component: Per-bar coloring support (
colorsarray for semantic color per bar, backward compatible) - i18n: Added
theme.*(3),chart.*(16),severity.*(3),alerts.summary,users.rankingTitle, andlogs.*(5 hourly-related keys) to both ja/en dictionaries
🟢 Added / 🔵 Fixed (Session 170 — Alert i18n structured refactor / Plan A)
- Supabase migration
002_alerts_i18n.sql(new): Addsdescription_template TEXT+description_params JSONBcolumns toalertstable (both nullable, backward compatible) +idx_alerts_templateindex proxy/cloud-logger.jscreateAlert(): Now acceptsdescription_template/description_paramsand writes them to Supabase. Legacydescription(Japanese completed string) kept for backward compatibilityproxy/cloud-logger.jscheckAlertRules(): Emits structured params for 3 alert sites (large_payload/bypass_attempt/prompt_injection)proxy/index.js: Emits structured params forpayment_failed(Stripe webhook) andinjection_in_upload(file upload)admin/src/App.jsx: AddedformatAlertDescription()/formatAlertType()helpers. Prefersdescription_template, falls back to legacydescription. Avoids printing raw key when template is not registeredadmin/src/i18n/{ja,en}.json: Added 5alert.type.*keys + 5alert.*template keys (with) to both ja/en- Known limitation: Injection label itself (e.g.,
制限の解除試行) is hardcoded Japanese in core/. Stored as-is in params; admin templates translate only the surrounding text. Future: core/ ENUM refactor
🟡 Changed (Session 170 — Color guideline compliance)
admin/src/App.jsx: Added--warnCSS variable per design guidelines (#d4956awarm amber). Light mode uses#b6824afor better contrast. Migrated "warning/risk" usages from harsh red--accent2to softer--warn(Critical Alerts numbers, Injections Detected numbers, off-hours large number, severity critical number,.pii-tag.danger)admin/src/lib/chart-theme.js: Updatedwarningpalette semantic to derive from--warn(was--accent3gold). Changedseries[1]fromaccent2towarnadmin/chart usages: PII detections, PII type, user PII, off-hours bars now usecolor: "warning"instead of"danger"(reserving--accent2for true errors only)
🟢 Added (Session 169 — Team Management Tab)
landing/console.html: Added 👥 Team Management tab. Business+ users get full features (member list, invite, remove). Free/Starter users see a Business upgrade prompt (PLG gate)landing/console.html: Detects?team_accept=1URL parameter and auto-callsPOST /team/accept(invitation acceptance flow from email links)proxy/index.js: UpdatedmaxMembersMapto{ free:1, starter:1, business:10 }(was{ starter:5, business:50 })
🔴 Breaking / ⚪ Docs (Session 162 — P-17 RAG v2 clean-start)
@pii-firewall/ragv0.0.0-archived: Legacy implementation archived.rag/src/renamed torag/src.history-2026-05-11/(git history preserved). Legacy API now returns 503 stub- New design docs (internal-docs only): P-17 RAG Pipeline design v2 (portable library covering P-14 / Node SDK / Python SDK / MCP across 4 execution contexts) + Core TTL env-var design (
PIIFW_TOKEN_TTLas an independent design doc) - Two legacy design docs archived:
p17-secure-rag-pipeline-design.md(former v0.2.1) andrag-core-integration-design.mdarchived because they do not meet the new standard (Architecture Principles v1.1 + Design Doc Guide v1.1) - New
@pii-firewall/ragimplementation will start after P-17 v2 design approval. Until then, legacy API calls return aRAG_ARCHIVEDerror (503)
⚪ Docs / 🟢 Added (Session 158 — SSoT bundle-copy sync CI script)
scripts/sync-credential-patterns.js(new): Treatscore/data/credential-patterns.jsonas SSoT and verifies or writes the Python SDK / Java SDK bundle copies. Supports--check/--write/--cimodes. Also verifies the<include>credential-patterns.json</include>registration in Java's pom.xml (Session 156 incident protection)package.json: Addednpm run sync:patterns/npm run sync:patterns:check.github/workflows/ssot-sync-check.yml(new): On PR / push touchingcredential-patterns.json, automatically runs--check --ciand fails on drift (Java repo is separate and skipped in CI)internal-docs/design/credential-patterns-design.md: Documented the new sync workflow (npm run sync:patterns) in §1internal-docs/design/p15-web-security-scanner-design.md: Major redesign in Session 158. Repositioned as "PII + Injection + LLMjacking integrated defense engine"; web scan integrated into existing 4 Tiers; switched to local execution model
🟢 Added (Session 157 — P15-2: LLMjacking Threat Intelligence Engine)
core/src/pii-detector.jsloadCredentialPatterns(): AddedcostEstimate/provider/tagsfield mapping when loading credential patternscore/src/pii-detector.jsdetectPII(): Credential pattern matches now pass throughrisk/costEstimate/provider/tags/remediationfields in candidate objects. Standard PII patterns (email, phone, etc.) do not carry these fields — backward compatibleproxy/index.js/detectendpoint: Candidates withcostEstimateortags: ["llmjacking"]are enriched with allmjacking_contextobject containingthreat/estimated_daily_cost/provider/tags/remediation(array) /reference- ZAP Groovy already complete (Session 155 v0.2.0 already outputs
costEstimate/remediationin alert descriptions)
🔵 Fixed (Session 156 — Java SDK: pom.xml resource include missing)
pii-firewall-java/pii-firewall-java-core/pom.xml: Addedcredential-patterns.jsonto<build><resources><resource><includes>. The file was added to resources in Session 155 but not registered in pom.xml, causinggetResourceAsStream("credential-patterns.json")to returnnull. After fix:mvn test89 tests, 0 Failures, 0 Errors (commit31db33f)
🟢 Added (Session 155 — P-JSON++: SSoT integration for ZAP Groovy / Python SDK / Java SDK)
scanner/zap-rules/piifw-passive-scan.groovyv0.2.0: Removed 15 hardcoded patterns. Now loads/zap/wrk/core/data/credential-patterns.jsonviaJsonSlurper, expanded to 19 patterns (Replicate / AWS STS / Docker Registry Token added). Alerts now includeid/provider;cwe/wascIdare read dynamically from JSONscanner/docker-compose.yml+.github/workflows/weekly-web-scan.yml: Addedcore/data/mount as/zap/wrk/core/data:ro(both local and GHA)python-sdk/pii_firewall/_local/credential-patterns.json(new): SSoT bundled copy. Included in wheel via[tool.setuptools.package-data]inpyproject.tomlpython-sdk/pii_firewall/_local/detector.py: Addedload_credential_patterns()(cached). The hardcodedapi_keyregex inPATTERNS_JA/PATTERNS_EN_UNIVERSALis replaced with a JSON-driven spread. Python SDK detection expanded by 9 additional typespii-firewall-java/pii-firewall-java-core/src/main/resources/credential-patterns.json(new): SSoT bundled copy (packaged in jar)RegexEngine.java: AddedloadCredentialPatterns(). Reads viagetResourceAsStream("/credential-patterns.json"), appended to BOTHjaPatternsandenPatterns(credentials are language-agnostic). RemovedAPI_KEYentries frompii-patterns.json(ja + en)
🔴 Breaking (Session 155 — Python SDK / Java SDK detection type granularity)
- Python SDK
detect_pii()/mask_pii(): Oldtype === "api_key"is replaced by 19 individual pattern IDs (anthropic-api-key, etc.) - Java SDK
Detection.type: Old"API_KEY"is replaced by 19 individual pattern IDs (anthropic-api-key, etc.). Downstream code branching onhasType(hits, "API_KEY")must migrate
🟢 Added (Session 154 — P-JSON / P-JSON+: Credential Patterns Single Source of Truth)
core/data/credential-patterns.json(new): Source of truth data file for 19 credential patterns. Schema:id/name/regex/risk/confidence/cwe/wascId/tags/provider/costEstimate/remediation. Includes Anthropic / OpenAI / Google AI / AWS / GitHub PAT / Stripe Live / HuggingFace / Groq / Perplexity / Replicate (10 existing) + JWT / Google OAuth / Slack Bot / Slack User / SSH Private Key / DB connection strings / Basic Auth URL / AWS STS / Docker Registry Token (9 new)core/src/pii-detector.js: AddedloadCredentialPatterns()function. The hardcodedapi_keyregex inPATTERNS_JA/PATTERNS_EN_UNIVERSALis replaced with JSON-based loading.mask_pii()/detect_pii()detection coverage expanded by 9 additional types (JWT / Google OAuth / Slack Bot/User / SSH / DB / Basic Auth / AWS STS / Docker)
🔴 Breaking (Session 154 — Credential detection type granularity)
mask_pii()/detect_pii()typefield: Previously all 10 credential variants were returned under a singleapi_keytype. They now return individual pattern IDs (anthropic-api-key/openai-api-key/stripe-secret-key-live/aws-access-key-id/github-pat/huggingface-token/groq-api-key/perplexity-api-key/replicate-api-key/google-ai-key, etc.). Downstream code branching ontype === "api_key"must migrate to individual IDs ortags-based matching
🟡 Changed (Session 151 — Task C: Extracted 3 remaining hardcoded inventories to JSON / separate files)
proxy/data/ai-providers.json(new): Source of truth for 25 Shadow AI monitored services. Replaces the inlineDEFAULT_AI_SERVICESarray inproxy/index.js. Future additions and policy changes are now handled by editing this JSON only (no code changes)proxy/index.js:DEFAULT_AI_SERVICESis now loaded viarequire("./data/ai-providers.json").services. The 30-line inline definition is reduced to 2 linesproxy/data/ui-providers.json(new): Source of truth for Developer Console UI provider settings (PROVIDERS / COMING_SOON). Contains models, API key acquisition steps, icons/colors for OpenAI / Anthropic / Google. COMING_SOON expanded to include DeepSeek / xAI / Together / Perplexityproxy/providers.js: Reduced to a thin wrapper that loads from ui-providers.json. 115 lines → 21 linesextension/content/monitored-sites.js(new): Exposes Extension's file PII scan target sites via global variablePIIFW_MONITORED_FILE_SITES. Loaded before content.jsextension/content/content.js:FILE_INPUT_SITESnow referencesPIIFW_MONITORED_FILE_SITESfrom monitored-sites.js (with fallback to legacy 3-site list if undefined)extension/manifest.json: Extendedcontent_scripts[0].jsto["content/monitored-sites.js", "content/content.js"]to guarantee load orderinternal-docs/design/ai-providers-coverage.md: Marked all 3 hardcoded inventory items in § 5-1 as ✅ complete. Updated § 6 add/update flow to JSON-based procedure
🔵 Fixed (Session 151 — NER performance test flakiness)
python-sdk/tests/test_local_detector_ner.py: Relaxedtest_performance_long_textthreshold from 500ms to 1500ms. The GiNZaja_ginzamodel's warm-state latency for 1200-character text is measured at 501-511ms, so the original 500ms threshold caused near-constant flakiness. This is a test design issue (threshold setting), not a core detection engine bug
🟢 Added (Session 151 — Python SDK generic wrapper refactoring: arbitrary provider support)
python-sdk/pii_firewall/wrap.py: New module. Exposeswrap_function(fn)/wrap_async_function(fn)/wrap_client(client, format). Wraps anystr -> strfunction or LLM SDK client with PII masking and restorationpython-sdk/pii_firewall/providers/openai_compatible.py: New module.OpenAICompatible(api_key=, base_url=)provides drop-in support for any OpenAI-compatible API (DeepSeek / xAI Grok / Mistral / Groq / Together AI / Perplexity / Fireworks / Azure OpenAI).AsyncOpenAICompatibleasync variant includedpython-sdk/pii_firewall/__init__.py: Exportedwrap_function/wrap_async_function/wrap_clientas public APIpython-sdk/tests/test_wrap.py: Added 10 tests (wrap_function 4, wrap_async_function 1, wrap_client OpenAI 3, wrap_client Anthropic 1, integration 1)python-sdk/tests/test_providers.py: Added 5 tests (OpenAICompatible 4, AsyncOpenAICompatible 1)- Backwards compatibility: Existing
from pii_firewall import openai / anthropic / geminidrop-ins remain fully functional. New API is added alongside (no breaking changes)
🟢 Added (Session 151 — Shadow AI registry expansion: 9 services added)
proxy/index.js: Added 9 entries toDEFAULT_AI_SERVICES(id 17-25): DeepSeek (monitoring), xAI Grok (monitoring), Azure OpenAI (approved), AWS Bedrock (approved), Vertex AI (approved), GitHub Copilot (monitoring), Cursor (monitoring), Notion AI (monitoring), DeepL Write (monitoring). Coverage now spans enterprise standards (Azure / Bedrock / Vertex), emerging providers (DeepSeek / xAI), coding tools (Copilot / Cursor), and SaaS integrations (Notion / DeepL). Domain matching limitations (hostname endsWith only — no path/regex support) documented in "8. Known Technical Limitations" of the internal master doc
🟢 Added (Session 143 — OA-2: Outlook Add-in API key auth, advanced injection detection)
outlook-addin/taskpane/taskpane.js/landing/outlook-addin/taskpane.js: Updated to v1.2. AddedPROXY_URLconstant (https://pii-firewallproxy-production.up.railway.app). AddedcurrentApiKey/hasConsentstate variables.loadSettingsFromRoaming()restores API key and consent state fromroamingSettingson startup. NewhandleAdvancedInjectClick()implements 3-state routing: no consent → consent modal → API key input → scan.saveApiKey()/clearApiKey()/updateApiKeyUI()/maskApiKey()handle key management UI.runAdvancedInjectionScan()calls proxy/detect-all-injectionsand renders results into#injection-list.callAdvancedInject()handles 401 (invalid key → clear + show input), 429 (quota exceeded), and network errors individually.normalizeAdvancedResults()normalizes proxy response formats A ({injections:[]}) and B ({results:[]})outlook-addin/taskpane/taskpane.html/landing/outlook-addin/taskpane.html: Added collapsible#api-key-sectioninside#read-section(shown after consent). Contains password input, save button, delete button, and console link. Changed#btn-advanced-injecthandler fromshowConsentModal()tohandleAdvancedInjectClick(). Updated consent modal copy to "API key required (all plans)" (previously "Starter plan or higher required")outlook-addin/taskpane/taskpane.css/landing/outlook-addin/taskpane.css: Added API key section styles:.api-key-section/.api-key-header/.api-key-hint/.api-key-row/.api-key-input/.btn-api-save/.api-key-status.success/.api-key-status.error/.api-key-footer-row/.btn-api-clear/.api-key-console-link
🟢 Added (Session 142 — OA-1: Outlook Add-in read mode, incoming email injection detection)
outlook-addin/taskpane/taskpane.js/landing/outlook-addin/taskpane.js: Updated to v1.1. Added read mode support.Office.onReadynow auto-detects mode viatypeof item.subject === 'string'(read vs. compose). RegistersOffice.EventType.ItemChangedhandler (Mailbox 1.5+, failure is non-fatal). NewdetectInjectionsLocally(text, lang)function inlines Phase 1 patterns fromcore/src/injection-detector.js— 11 pattern groups for both JA and EN.normalizeForInjection()handles hiragana→katakana, full-width→half-width, and zero-width character removal. Detection results shown at two severity levels: critical (危険) and warning (警告).roamingSettings-based consent management added as prerequisite for OA-2 Proxy integrationoutlook-addin/taskpane/taskpane.html/landing/outlook-addin/taskpane.html: Updated v1.0 → v1.1. Added#mode-indicator,#read-section(with#injection-banner,#injection-results,#injection-list,#injection-safe,#btn-advanced-inject),#compose-sectionwrapper, and consent dialog modaloutlook-addin/taskpane/taskpane.css/landing/outlook-addin/taskpane.css: Added mode indicator styles (.mode-compose/.mode-read), injection warning banners (.injection-banner-critical/-warning/-safe), detection list items (.injection-item.critical/.warning), consent modal overlay (.consent-overlay/.consent-modal), and.btn-advancedoutlook-addin/manifest.xml/landing/outlook-addin/manifest.xml: Added<Form xsi:type="ItemRead">to FormSettings. AddedMessageReadCommandSurfaceExtensionPoint ("インジェクション検知" button in read-mode ribbon). Updated Mailbox requirement from 1.3 → 1.5 (forItemChangedsupport)
🟡 Changed (Session 142 — OA-Privacy: Outlook Add-in Privacy by Design compliance, local processing)
outlook-addin/taskpane/taskpane.js/landing/outlook-addin/taskpane.js: Changed PII detection from Proxy/detectserver-side call to browser-local regex engine. RemovedPROXY_URLconstant. Implemented newdetectPIILocally(text, lang)function (inlines PATTERNS_JA with 19 types and PATTERNS_EN with 11 types fromcore/src/pii-detector.js). Email body text no longer transmitted to any external server — fully Privacy by Design compliant. Includes full-width→half-width normalization, deduplication, and infinite-loop protection for both JA and EN modes
🟢 Added (Session 141 — FE-2: Tika production integration in docker-compose.selfhosted.yml)
proxy/docker-compose.selfhosted.yml: Addedtikaservice (apache/tika:latest-full,internal: truenetwork isolation,JAVA_TOOL_OPTIONS=-Xmx1g, health check). AddedTIKA_URL: http://tika:9998env var anddepends_on: tikatopiifw-proxy. Self-hosted Proxy customers can now start a full Tika-enabled environment with a singledocker compose upproxy/file-extractor.js: Extended Tika timeout from 30s to 120s (scanned PDF OCR can take up to 2 minutes)
🟢 Added (Session 140 — Apache Tika integration, expanded file format support)
proxy/file-extractor.js: AddedextractWithTika()function. Self-hosted Proxy (withTIKA_URLenv var set) can now extract text from scanned PDFs, images (PNG/JPG/TIFF/BMP), legacy PowerPoint (.ppt), and email files (.eml/.msg). Automatically skipped on SaaS version (noTIKA_URL) for Privacy by Design complianceproxy/file-extractor.js: Added automatic OCR fallback to Tika when PDF text extraction returns empty content (scanned/image PDFs)internal-docs/design/file-extraction-design.md: New design document for Apache Tika integration (v1.1 PoC complete). Covers architecture, Docker Compose config (internal: trueoutbound isolation), Privacy by Design compliance, PoC results (digital PDF <1s / scanned PDF OCR 46.7s), and OCR UX policyinternal-docs/sales/competitor-analysis.md: Added detailed PII Tools research. Documents their technical stack (Apache Tika + Tesseract), founder profile, and comparison table vs PIIFirewall
🟡 Changed (Session 138 — Add noindex to index-v2.html)
landing/index-v2.html: Added<meta name="robots" content="noindex, nofollow">to prevent search engine indexing of the in-progress v2 page. Must be removed before production launch.
🟡 Changed (Session 138 — Injection-related content made private)
landing/index.html: Removed all injection attack detection/defense content from the landing page due to pending patent application. Includes nav links, Problem card, Feature card, demo tab, SDK code examples, and all JA/EN i18n stringslanding/blog.html: Removed article cards forprompt-injection.htmlandindirect-injection-rag.html(3 instances)landing/_redirects: Added 301 redirects forsolutions/injection-defense,blog/prompt-injection, andblog/indirect-injection-rag→piifirewall.com
⚪ Docs (Session 137 — P14-5 Self-hosted Proxy Setup Guide)
docs/ja/api/self-hosted-proxy.md/docs/en/api/self-hosted-proxy.md: New Self-hosted Proxy setup guide (JA/EN). Covers quick start (5 steps), environment variable reference, storage configuration (memory/Redis/PostgreSQL), Docker Compose instructions, air-gap mode, SHA256 image verification, Privacy by Design data disclosure, token loss risk warning, and troubleshootingdocs/.vitepress/config.ts: Added Self-hosted Proxy link to the "Infrastructure & Operations" / "インフラ・運用" sidebar section in both JA and EN
🟢 Added (Session 137 — P14-4 GitHub Actions GHCR Multi-arch Build)
.github/workflows/docker-ghcr.yml: New GitHub Actions workflow for Self-hosted Proxy. Triggers onproxy-v*tag push to buildlinux/amd64+linux/arm64simultaneously viadocker buildxand push to GHCR private registry (ghcr.io/kmishimaslgithub/pii-firewall/proxy). Automatically appends SHA256 digest to GitHub Release notes for tamper verification. GitHub Actions cache integration for faster subsequent builds. Also supports manual builds viaworkflow_dispatch
🟢 Added (Session 136 — P14-3 License key authentication)
proxy/license-auth.js: New Self-hosted Proxy license authentication module. Ed25519-signed JWT verification (syntax, expiry, issuer claims). Full signature verification when public key (proxy/certs/piifw_license_public.pem) is present. Supports both air-gap mode (PIIFW_LICENSE_FILE) and standard mode (PIIFW_LICENSE_KEY)proxy/migrations/001_license_keys.sql: Supabase migration SQL for newlicense_keysandlicense_usagetables with RLS policy and auto-updatedupdated_attriggerproxy/index.js: Added startup license check (rejects boot withprocess.exit(1)if license is invalid whenPIIFW_LICENSE_KEY/PIIFW_LICENSE_FILEis set),/license/refreshendpoint (manual monthly report trigger), license info in/healthresponse, API call count middleware (Self-hosted mode only), and automatic 30-day monthly report viasetInterval
🟢 Added (Session 135 — P14-1 Self-hosted Proxy Dockerfile)
proxy/Dockerfile.selfhosted: New Dockerfile for P-14 Self-hosted Proxy distribution. Multi-stage build (deps → production), non-root user (nodeUID=1000),linux/amd64+linux/arm64support, built-in health checkproxy/docker-compose.selfhosted.yml: Customer-facing Docker Compose file with Redis / PostgreSQL optional configurations included as commented-out examplesproxy/certs/.gitkeep: Directory for Ed25519 public key placement (P14-7 will addpiifw_license_public.pem).dockerignore: Excludes secrets and unnecessary frontend files from Docker build context
⚪ Docs (Session 134 — GiNZa NER extension developer documentation)
docs/ja/guide/limitations.md/docs/en/guide/limitations.md: Added "NER Extension Option (Python SDK) — Enhanced Name Detection" section. Includes detection comparison table for katakana/rare-kanji names, recommended industries (healthcare, HR, legal, finance, government), installation example, and platform availability noticedocs/ja/api/sdk.md/docs/en/api/sdk.md: Added Python SDK NER extension tip box directly after the name detection warninginternal-docs/design/python-sdk-design.md: Added platform NER coverage matrix (Python SDK / LangChain / Proxy / MCP / Node.js SDK / Chrome Extension / Java SDK)
🔵 Fixed (Session 130 — CORS log noise suppressed)
proxy/index.js: Requests without anOriginheader (e.g. Railway health checks) were logging[CORS] origin: undefinedevery minute. Fixed by returning early withallowbefore logging whenoriginis undefined.
🟡 Changed (Session 128 — Developer Console UI improvement)
- Developer Console (
landing/console.html): Added a prominent yellow warning box on the TOTP 2FA screen to distinguish it from the email OTP step. Text now clearly states "This is not the email code" and label changed to "Authenticator app code (6 digits)"
⚪ Docs (Session 125 — Plan tables major revision & feature additions)
- All 4 files (
docs/ja/api/plans.md·docs/en/api/plans.md·docs/ja/guide/plans.md·docs/en/guide/plans.md) updated - Simplified API call limits (removed unified credit system): Free 300 · Starter 10,000 · Business 300,000 (was 333,333) · Enterprise unlimited
detect_injection·detect_all_injections·detect_sql_injectionnow unlimited on all plans- Added to feature tables:
detectAllInjections(SQL + prompt composite),detectSQLInjection,langoption,maskMessages - Team member invites: Starter ✅→❌ (single-seat) · Business ✅ clarified
- Add-on packs: renamed unit from "credits" to "API calls"
- Guide docs: removed unified-credit web-app complexity, simplified to API call model
⚪ Docs (Session 125 — Plan feature table corrections)
docs/ja/api/plans.md·docs/en/api/plans.md: Fixed Custom PII rules availability for Starter from ❌ to ✅ in both SDK and REST API tables (reflecting the 2026-04-29 change). Unified PII types display to "24 + custom" for Starter/Business/Enterprise. Updated FAQ wording.docs/ja/guide/plans.md·docs/en/guide/plans.md: Fixed Custom PII rules Starter ❌→✅, PII types display, Team member invites Starter ✅→❌ (Starter is single-user), updated FAQ wording.
🔵 Fixed (Session 119 — logo-light.svg was empty due to PS regex write failure)
docs/public/logo-light.svgandinternal-docs/public/logo-light.svgwere previously written as empty files due to a PowerShell regex variable write failure. Fixed by using IndexOf/Substring string manipulation on the confirmed-workinglogo-dark.svgcontent.
🎨 Changed (Session 119 — Logo light/dark split with darker navy)
- Replaced
logo-adaptive.svgwith separatelogo-light.svg/logo-dark.svgin both docs and internal-docs - Light mode: rounded navy background (
#0a1929, darker/blacker than before) so the shoebill remains visible - Dark mode: transparent background so the shoebill bird floats alone against the site's dark background
- Uses VitePress
logo: { light, dark }syntax for reliable theme switching (SVG media queries in<img>tags are unreliable) - Fixed: artboard border polyline removed from source SVG — was causing square appearance over rounded corners
🎨 Changed (Session 118 — Adaptive SVG logo for docs nav)
- Replaced nav logo in docs and internal-docs with
logo-adaptive.svg. Uses SVG@media (prefers-color-scheme): light mode → navy background, dark mode → transparent (blends with site background)
🎨 Changed (Session 118 — Logo icon full redesign)
- Unified logo across all products (landing / app / extension / admin) with new "Shoebill Shield" design
- Design: Shoebill stork × shield motif, rounded corners (rx=460), dark navy (#10365a) background
- Updated files: all PNGs in
landing/icons/,app/public/icons/,extension/icons/,admin/favicon.svg, favicon.ico, apple-touch-icon.png, PWA icons (192/512px)
🔵 Fixed (Session 115 — TOTP stuck UX bug)
landing/console.html— Added "← Back to email input" link on TOTP challenge screen (login-step3). Users can now escape if they can't access their authenticator app.resetToLoginStep1()signs out the Supabase session and resets all login steps
🟢 Added (Session 115 — P-05 Console UI Webhook tab)
landing/console.html— Added "🔔 Webhook" tab to Settings panel. Features: endpoint registration form (URL, event selection, description), registered endpoint list (test send, secret rotation, delete), one-time full secret display with clipboard copy, delivery history table (timestamp, event, status, retry count, error). Free plan shows Starter+ upgrade gate
🟢 Added (Session 115 — P-05 WebhookDispatcher implementation)
proxy/index.js— AddedWebhookDispatcherclass. Fire-and-forget async delivery, HMAC-SHA256 signing, exponential backoff retry (up to 3x: 1s→2s→4s), 5-second timeout, delivery log recording. Privacy by Design: payload never contains raw PII, masked_text, or token valuesproxy/index.js— Addedpii.detectedWebhook dispatch to/maskendpoint (API-key authenticated, Starter+, PII detected only)proxy/index.js— Addedinjection.detectedWebhook dispatch to/detect-all-injectionsendpoint (opt-in, OFF by default)proxy/index.js— Added Webhook management REST API:GET/POST /webhooks(list/register),PATCH/DELETE /webhooks/:id(update/delete),GET /webhooks/:id/logs(delivery history),POST /webhooks/:id/test(test send),POST /webhooks/:id/rotate-secret(secret rotation)proxy/index.js— AddedgenerateWebhookSignature()HMAC-SHA256 signature helperproxy/index.js— AddedvalidateWebhookUrl()SSRF protection (HTTPS required, private IP blocked)proxy/supabase-migrations/008_webhook_endpoints.sql—webhook_endpointstable migration (applied to Supabase production)proxy/supabase-migrations/009_webhook_logs.sql—webhook_logstable migration (applied to Supabase production)
🟢 Added (Session 113 — P-04 Framework Middleware implementation)
python-sdk/pii_firewall/middleware/_base.py— New shared masking utility_mask_body(). Fully delegates toPIIFirewallinstance (no direct_localdependency). Default scan fields:messages/text/prompt/query/inputpython-sdk/pii_firewall/middleware/fastapi.py— New FastAPI / Starlette ASGI middleware (PIIFirewallMiddleware). Single-line integration:app.add_middleware(PIIFirewallMiddleware).on_license_error="block"default (Autonomous Stop principle). Zero-code integration via ASGIreceiveoverridepython-sdk/pii_firewall/middleware/flask.py— New Flask WSGI middleware (PIIFirewallFlask). Zero-code integration via WSGIenviron["wsgi.input"]replacement —request.get_json()returns pre-masked data automaticallypython-sdk/pii_firewall/middleware/django.py— New Django middleware (PIIFirewallDjango). Zero-code integration viarequest._bodycache override —request.body/request.data(DRF) return pre-masked data automatically. Configured viasettings.pyPII_FIREWALLkeypython-sdk/pii_firewall/middleware/__init__.py— Exports all 3 middleware classespython-sdk/pyproject.toml— Addedfastapi/flask/djangooptional-dependenciessdk/src/middleware.js— AddedcustomPatterns/langargs to Express / Hono / Fastify sharedmaskBody(). Addedquery/inputfields to default scan targetssdk/src/index.js— FixedexpressMiddleware()/honoMiddleware()/fastifyPlugin()to propagatecustomPatterns/langtomaskBody()
🟢 Added (Session 112 — Custom PII dictionary: full SDK implementation)
sdk/src/index.js/sdk/src/index.d.ts—createFirewall({ customDictionary })support. AddedCustomDictionary,CustomKeyword,CustomPatterntypes. Patterns compiled at instance creation; auto-applied tomask()/maskMessages()/detect()python-sdk/_local/detector.py— Addedbuild_custom_patterns(entries)(Python port of JSbuildCustomPatterns). Addedcustom_patternsarg todetect_pii()python-sdk/_local/masker.py— Addedcustom_patternsarg tomask_pii()python-sdk/client.py—PIIFirewall(custom_dictionary=...)support. Acceptspii-dictionary.jsondirectly. Auto-applied tomask_pii()/detect_pii()mcp-server/src/index.js— Addedcustom_dictionaryparameter tomask_pii/detect_piitoolslangchain-plugin/callbacks.py—PIIFirewallCallbackHandler(custom_dictionary=...)supportlangchain-plugin/tools.py—get_pii_tools(custom_dictionary=...)support
🟡 Changed (Session 112 — Custom PII dictionary plan restriction update)
proxy/index.js— Removed plan-based restrictions on custom PII dictionary: keyword count limit (previously Starter=10 entries) abolished; regex patterns now allowed on all paid plans (previously Business+ only). Plan differentiation axis changed from "dictionary size" to "user count (Starter=1 user / Business=team)".
🔵 Fixed (Session 110 — proxy Webhook flow fix & SDK Billing Phase 2 full test)
proxy/index.js— ChangedissueSdkKeyimport to direct reference from../core/src/billing(workaround for stale npm workspace symlink)- Stripe Webhook endpoint path unified to
/stripe/webhook scripts/sdk-billing-test-phase2.js— New regression test script for Stripe Webhook → sdk_keys auto-issue flow (10/10 PASS confirmed)
🟢 Added (Session 109 — P-03 OpenAI / Anthropic Drop-in Wrappers)
python-sdk/pii_firewall/openai.py— New OpenAI SDK drop-in wrapper. Change just one import (from pii_firewall import openai) to protect any existing code. ProvidesOpenAI/AsyncOpenAIwith automatic pre-send PII masking and post-receive PII restore, including streaming support viaPIIFirewallStreampython-sdk/pii_firewall/anthropic.py— New Anthropic SDK drop-in wrapper. Change just one import (from pii_firewall import anthropic) to protect any existing code. ProvidesAnthropic/AsyncAnthropicpython-sdk/pii_firewall/_wrapper/messages.py— Shared message-array mask/restore logic for OpenAI / Anthropicpython-sdk/pii_firewall/_wrapper/stream.py—PIIFirewallStreamstreaming wrapper (sync + async)python-sdk/pyproject.toml— Addedopenai/anthropic/alloptional-deps
🔵 Fixed (Session 102 — api_usage FK constraint removal)
proxy/supabase-migrations/007_api_usage_drop_fk.sql— Removed FK constraint (api_usage_api_key_id_fkey) fromapi_usage.api_key_id. SDK keys (UUIDs fromsdk_keystable) can now be recorded inapi_usage. Design usestype='proxy'/type='sdk'to distinguish records
🔵 Fixed (Session 102 — OTP input digit count fix)
landing/index.html,landing/index-v2.html— Fixed auth modal OTP input from 8 digits to 6 digits (Supabase sends 6-digit OTP)
🟢 Added (Session 98 — Real-time PII detection improvement & multi-site send interception)
extension/content/content.js— Improved detection reliability and Google AI support- Added 1.5-second polling of the focused input element (
startInputPolling/stopInputPolling). PII badge now appears in real-time on sites with unreliableinputevents (ChatGPT new UI, Google AI, etc.) - Added
keyup,compositionend,focusinevents to all listener attachment points - Added
quickLocalCheck()— instant regex-based PII check at send time (no API, synchronous) - Added
findActiveInput()— resolves active input from polling state or focus history - Updated
onKeyDown/onButtonClick: two-phase interception — Phase 1 (async detection ready → mask) + Phase 2 (no prior detection → quick check → badge) - Expanded
SEND_BUTTON_SELECTOR: addedbutton[type="submit"],button[jsname="c8mGvb"],button[jsaction*="send"]for Google AI
- Added 1.5-second polling of the focused input element (
🔵 Fixed (Session 98 — ChatGPT token format normalization)
extension/content/content.js— ChatGPT strips[SECURED:type=name,id=xxx]to[SECURED=name,id=xxx]in responses; extension now handles both formatsscanResponsesForTokens(): broadenedinnerHTMLcheck to detect both[SECURED:type=and[SECURED=getResponseText(): broadened text match to include both token formatsgetFirstTokenId(): updated regex to[SECURED(?::type=|=)...](matches both formats)- Added
normalizeSecuredTokens()— converts[SECURED=name,id=xxx]→[SECURED:type=name,id=xxx]before sending to proxy applyRestoreText(): appliesnormalizeSecuredTokens()before sending to proxy
🟢 Added (Session 98 — Extension masking via Proxy, AI response restore, MCP billing)
extension/background/background.js— 2 new handlersPROXY_MASK: calls/mask(cryptographic tokenization; free plan, no API key required)PROXY_RESTORE_TEXT: calls/restore-text(free plan, no API key required)
extension/content/content.js— masking and restore enhancementsapplyMask()made async; now calls Proxy API/maskto produce[SECURED:type=xxx,id=yyy]tokens (falls back to local masking if proxy unavailable)- AI response restore: detects
[SECURED:tokens in ChatGPT / Claude.ai / Gemini response areas → shows fixed bottom-right "🔓 Restore" badge → restore result panel with copy support - Added
scanResponsesForTokens()/scheduleResponseScan(), integrated into MutationObserver
extension/content/content.css— styles for restore badge (#piifw-restore-badge) and restore panel (#piifw-restore-panel)mcp-server/src/index.js— SDK shared billing module integrated- Startup:
loadKey()(PIIFW_LICENSE_KEYenv →~/.piifw-license.json) +startPolling() - Per tool call:
billableCheck()—checkQuota()+incrementCounter()(applies to:mask_pii,detect_pii,detect_injection,detect_all_injections,rag_ingest,rag_resolve) BillingErrorreturned as structured error (QUOTA_REACHED/KEY_EXPIRED)- No-key (free) mode: billing check skipped; proxy-side rate limiter applies
- Startup:
🟢 Added (Session 97 — Extension billing)
extension/background/background.js— API key support- Shadow AI URL detection (
/shadow-ai/check): skipped when no API key; addsAuthorization: Bearerheader when key is set - Injection detection (
/detect-injection): returns{ ok: false }immediately when no API key - Added
SET_API_KEYmessage handler (save / remove fromchrome.storage.sync) - Added
piifw_api_keytoGET_SETTINGS
- Shadow AI URL detection (
extension/popup/popup.html+popup.js— Settings tab and API key UI- New "⚙️ 設定" tab (API key input, save, clear; proxy URL change)
- Shadow AI tab: shows lock UI (🔒) with "Set API Key" button when no key is configured
- All Shadow AI features unlocked immediately once API key is saved
proxy/index.js— API key required for paid endpointsPOST /detect-injection— returns 401API_KEY_REQUIREDwithout keyPOST /detect-all-injections— samePOST /shadow-ai/check— same
🟢 Added (Session 96 — SDK Billing Phase 4)
proxy/sdk-key-routes.js— AddedPOST /sdk/key-checkendpoint (SDK daily polling receiver)- Key signature verification (KEY_EXPIRED allowed → triggers new key lookup flow)
- Upserts cumulative
call_counttoapi_usagetable (withtype: 'sdk') - Simultaneously updates Phase 3 chain state when
chain_hash/prev_hashprovided - Response:
{ status: 'active'|'new_key_available'|'expired', new_key?, quota_remaining? }
core/src/sdk-manager.js(new) — Client-side in-memory key management and daily pollingloadKey(options)— loads key from env var / file / direct arg into memorysaveKey(keyJson, filePath)— instantly updates in-memory key + persists to file (no restart needed)getInMemoryKey()— returns current in-memory keypollKeyCheck(options)— single call to/sdk/key-check; auto-applies new key if returnedstartPolling(options)— fires immediately on startup, then repeats every 24h (non-blocking)stopPolling()— stops the polling interval- Tests: 9 (loadKey / saveKey / getInMemoryKey)
core/index.js— Spread-exported allsdk-managerfunctionsproxy/supabase-migrations/006_api_usage_sdk.sql(new) — Addstypecolumn toapi_usage('proxy'/'sdk')
🟢 Added (Session 96 — SDK Billing Phase 3)
core/src/billing.js— Added hash-chain tamper detectioncomputeChainHash(prevHash, count, keyId, timestamp)— deterministic SHA-256 chain hash computationverifyChain(record, keyId)— counter file tamper detection (throws TAMPER_DETECTED; legacy format skipped for backward compatibility)readCounter()— extended to preserve Phase 3 chain fields (key_id / prev_hash / chain_hash / timestamp)incrementCounter(filePath, keyId)— addedkeyIdargument: verifies chain → computes new hash → persistsresetCounter(filePath, keyId)— addedkeyIdargument: initializes genesis chain (prev_hash = key_id)- Tests: 35 total (+9 Phase 3 tests)
core/index.js— Added exports forcomputeChainHashandverifyChainproxy/sdk-key-routes.js— AddedPOST /sdk/verify-chainendpoint (server-side chain verification: validates prev_hash, persists new chain_hash)proxy/supabase-migrations/005_sdk_chain.sql(new) — Addslast_chain_hash/last_call_count/chain_verified_atcolumns tosdk_keys
🟢 Added (Session 95 — SDK Billing Phase 2)
proxy/supabase-migrations/004_sdk_keys.sql(new) —sdk_keystable for storing signed SDK keys (with RLS enabled)proxy/index.js— Integrated SDK key auto-issuance into Stripe Webhookscheckout.session.completed: auto-issue SDK key on subscription purchase and save tosdk_keysinvoice.payment_succeeded: auto-issue renewal key on monthly cycle; mark previous key assuperseded
proxy/sdk-key-routes.js— AddedGET /sdk/my-keyendpoint (Supabase JWT auth; returns current active key for console display)
🟢 Added (Session 95 — SDK Billing Phase 1)
core/src/billing.js(new) — SDK billing & usage management module (Phase 1: basic stop enforcement)BillingError/BillingErrorCode(QUOTA_REACHED / KEY_EXPIRED / INVALID_KEY)issueKey()/signKey()— HMAC-SHA256 signed key generation (proxy/server side)verifyKey()— signature verification +valid_untilexpiry check (SDK side)checkQuota()— autonomous stop when API call count reachesquota_totalreadCounter()/incrementCounter()/resetCounter()— persistent local API call counter
proxy/sdk-key-routes.js(new) —POST /sdk/issue-key(admin-only signed SDK key issuance API)GET /sdk/key-info— HMAC configuration status check endpoint
core/index.js— Exportbillingmodule both as namespace and individually
🟢 Added (Session 91 — JPY pricing support)
proxy— Addedcurrencyparameter to/stripe/create-checkout-sessionand/stripe/create-credits-checkout(routes to JPY or USD price IDs)landing/index.html— Updated JA pricing display to ¥2,980/¥29,800 (Starter) and ¥49,800/¥498,000 (Business)landing/index-v2.html— Same: updated JA pricing attributes, added_pendingCurrency, and passedcurrencyparam in OTP redirect URLlanding/console.html— Post-OTP checkout andupgradeFromConsole()now passcurrencyto the checkout APIdocs/ja/guide/plans.md/docs/en/guide/plans.md— Added JPY price column (tax-exclusive note, annual discount, credit add-on table)docs/ja/api/plans.md/docs/en/api/plans.md— Added JPY column to plan overview table
🟡 Changed (Session 90 — Security)
landing/security.html— Replaced third-party service names with functional category descriptions (e.g., Railway → cloud hosting provider)docs/ja/api/seva.md/docs/en/api/seva.md— "Supabase pgvector" → "cloud vector DB" (infrastructure non-disclosure rule applied)docs/ja/guide/shadow-ai.md/docs/en/guide/shadow-ai.md— "via Supabase" → "via a cloud database"
🟢 Added (Session 90)
landing/security.html— New Information Security Policy page (JA/EN bilingual)- Privacy by Design 7-principle table, basic policy, incident response, third-party services, legal compliance
- Footer link added to
landing/index-v2.htmlunder the "Company" column (JA/EN i18n)
🟢 Added (Session 89)
proxy/index.js— Brute-force protection:express-rate-limitv7.5.1- Global limiter: all endpoints, 300 req / 15 min (blocks bots and scrapers)
- Auth limiter:
POST /api-keys,POST /user-api-keys/save, 20 req / 15 min (credential stuffing protection) - Chat limiter:
/chat,/chat-with-file,/chat-multi, 20 req / 1 min (cost-attack protection) - Added
app.set("trust proxy", 1)for correct real-IP detection behind Railway's reverse proxy /stripe/webhookis excluded from rate limiting- Limit exceeded: logs warning + returns
429 Too Many Requests
🟡 Changed (Session 87)
landing/console.html— Updated default test text to include custom dictionary keywords ("α計画", "機密") for clear before/after Dictionary demolanding/console.html— Added "🔑 Custom Dictionary: N keywords active" indicator in Request Body area when Dictionary is ON- Updates in real time on page load, toggle change, and Save
- Hidden when toggle is OFF
🔵 Fixed (Session 87)
landing/console.html— Dictionary tab: fixed bug where toggling ON did not addcustomDictionaryto the request- Root cause: if the user hadn't clicked "Save" before toggling ON, localStorage had no dictionary data and
getCustomDictionary()returned null - Fix: auto-save editor content when toggle is switched ON; shows error if JSON is invalid and reverts toggle
- Fallback added: if localStorage has no saved data, reads directly from editor content
- Root cause: if the user hadn't clicked "Save" before toggling ON, localStorage had no dictionary data and
🟢 Added (Session 88)
core/src/pii-detector.js— Japanese name detection without spaces (surname dictionary, ~400 entries)JAPANESE_SURNAMESSet (2+ char surnames only); longest surname matched first (長谷川 before 長谷)maskPII(text, ["name"], "ja")now masks names like "田中太郎" and "山田花子" without requiring a space- False-positive prevention: skips matches when immediately preceded/followed by address or company suffix chars (株, 式, 会, 社, 業, 機, etc.)
detectPIIreturns no-space names as{ type: "name", level: "confirm" }candidates- No double-masking with the existing space-based pattern ("田中 太郎")
- 9 unit tests added to
pii-detector.test.js
core/src/pii-detector.js— Single-char and multi-char surname detection via honorific/title contextJAPANESE_SURNAMES_1CHARSet (~50 single-char surnames: 林, 森, 原, 岡, 島, 谷, 野, etc.)HONORIFIC_TITLESarray (30+ items: さん/様/氏/くん/殿/部長/課長/社長/etc., longest-first matching)- 4 detection patterns:
- A) 1-char surname + honorific (林さん, 金様, 林氏, 南くん)
- B) 1-char surname + title suffix (森部長, 岡社長)
- C) [role]の[1-char surname]です (社長の菅です, 部長の原より)
- D) 2–4 char surname + honorific/title (小林さん, 田中氏, 長谷川様)
- Masks surname only, preserving honorific/title — e.g.
林さん→[SECURE_name_xxx]さん - False-positive prevention: skips when immediately preceded by kanji (compound words, place names)
- Added
HONORIFIC_KANJI_1CHARSet: gLen scan loop breaks before kanji honorifics (氏/様/殿/君) → Root-cause fix preventing "長谷川様" from being over-masked as "長谷川様" when "長谷" (a shorter surname) is also in the dictionary - 15 unit tests added to
pii-detector.test.js
⚪ Docs (Session 88)
docs/en/api/console.md— Renamed page to Test Console (was: API Test Console)docs/en/api/console.md— Added Custom Dictionary section: setup, ON/OFF toggle behavior, demo walkthrough, and localStorage storage detailsdocs/.vitepress/config.ts— JA/EN sidebars: moved Test Console and SEva to "Getting Started" section (was: Infrastructure & Operations)docs/en/guide/limitations.md— Updated name detection section from "space required" to "partial space-free support in progress". Added table showing current detection coverage (dictionary matching + honorific context)docs/ja/api/core-functions.md— UpdatedextraTypes: ["name"]info callout to reflect dictionary matching and honorific context support
⚪ Docs (Session 87)
docs/en/guide/pii-protection-levels.md— New page: PII Protection Levels by LLM- Comparison table for major LLMs (Claude / ChatGPT / Gemini / Copilot / Perplexity / Mistral / Llama / Local LLMs)
- How-it-works breakdown by route (Chrome Extension / API / MCP / SEva pipeline)
- Added to User Guide sidebar
docs/en/api/mcp.md— Added "Mask All Messages in a Session" tip- How to activate PII Firewall for an entire session with a single instruction at session start
🟢 Added (Session 86)
core/src/pii-detector.js— Custom PII Dictionary (Privacy by Design: dictionary data never stored on our servers)- Added
buildCustomPatterns(entries): converts keyword/regex entries into pattern objects compatible with the detection engine detectPII()/maskPII()— addedopts.customPatternsoption for dynamic pattern injection
- Added
proxy/index.js—/mask//detectendpoints now acceptcustomDictionaryrequest field- Tier-based validation: Starter = max 10 entries, keywords only; Business+ = regex patterns allowed; Enterprise = unlimited
- Format:
{ keywords: [{keyword, type}], patterns: [{pattern, type}] }
landing/console.html— Added 🔑 Dictionary tab- JSON editor, file upload, download, localStorage persistence
- Apply toggle: when ON, automatically injects
customDictionaryinto all test requests
🟡 Changed (Session 85)
core/src/pii-detector.js— English PII detection accuracy improvements (pii-masking-300k benchmark Micro F1: 65.02 → 75.48)- drivers_license UNIVERSAL labeled pattern extended:
isseparator support; lookahead updated to cross spaces/dots ((?=[A-Z0-9]{0,15}\d)→(?=[A-Z0-9\s\-\.]{0,40}\d)) - drivers_license value format extended: space-separated (
VIKAS 606107 9 539) and dot-separated (EFSEV.761144.EB.196) values now supported - drivers_license JSON key pattern added to UNIVERSAL:
"driver_license": "VALUE"format - postal_code context-required pattern added: partial UK outward-only codes (
CM3,RG7, etc.) via JSON key / XML tag / labeled format in UNIVERSAL - F1 score improvements: drivers_license 21.56→53.71, postal_code 33.11→73.85, Micro Avg 65.02→75.48
- drivers_license UNIVERSAL labeled pattern extended:
scripts/run-pii-masking-300k-benchmark.js— Benchmark accuracy improvements- Extended
normalizeValue()to strip DL and postcode JSON key prefixes - GT collection logic: split comma-separated multi-value entries for individual comparison (e.g.
"dn33eh,dn33eq"→ 2 separate GT values)
- Extended
🟢 Added (Session 84)
core/src/pii-detector.js— English Regional Detection Layer (Region-First Exclusive Architecture)- Added
detectRegion(text)function: score-based automatic detection of 6 regions (US/UK/IN/AU/SG/CA) + Generic fallback PATTERNS_EN_UNIVERSAL: patterns shared across all English modes (labeled/context-required only; no region-specific bare patterns)PATTERNS_EN_US/UK/IN/AU/SG/CA/GENERIC: per-region exclusive pattern sets (postal code, phone, passport, national ID)detectPII(text, "en", { region: "us" })— explicit region override option addeddetectRegion()exported viamodule.exports(available to SDK and testing)- Expected benchmark improvement: postal_code Recall 25%→50%+, drivers_license 14%→60%+
- Supported regions:
- 🇺🇸 US: bare ZIP (
12345), bare SSN, US state address, US phone(555) 123-4567, US DL, EIN - 🇬🇧 UK: UK postcode, NIN (with/without label), NHS number (with/without label), DVLA DL format, UK phone
07xxx - 🇮🇳 IN: Aadhaar (12-digit), PAN card, 6-digit PIN code, IFSC code, IN phone
9xxxxxxxxx - 🇦🇺 AU: state+4-digit postal, TFN, ABN, AU phone
02/04xx, Medicare card - 🇸🇬 SG: NRIC/FIN (
S/T/F/G+ 7 digits + check letter), 6-digit postal (S048616format), SG phone6/8/9xxxxxxx, UEN - 🇨🇦 CA: SIN (3-3-3 format, distinct from US SSN 3-2-4), Canadian postal
K1A 0B1, OHIP/health card, BN
- 🇺🇸 US: bare ZIP (
- Cross-region interference eliminated: CA documents no longer incorrectly match "IN" (from "SIN") as a US state abbreviation
- Added
🟡 Changed (Session 82)
core/src/pii-detector.jsPATTERNS_EN — Major pattern improvements (pii-masking-300k benchmark Micro F1: 57.85 → 65.02)- password: Changed to
\b(?:password|passwd)\b\s*[:=]\s*\S+. Removedpass/pwd, made[:=]mandatory. FP reduced by 77% (133→31) - phone: Added context-required pattern (
Phone: 0123456789form). Recall 42.4%→60.3%, F1 47.41→61.28 - passport XML: Extended from
<passport>\d{9}>to<passport>[A-Z0-9]{6,12}. Covers alphanumeric passports (e.g.A12345678) - drivers_license XML: Generalized tag to
<[A-Za-z]*licen[sc]e[A-Za-z]*>. Covers<driverslicense>,<drivinglicence>etc.
- password: Changed to
⚪ Docs
docs/ja/api/mcp.md/docs/en/api/mcp.md— Added "Auto PII Protection Setup (Recommended)" section. Documents Method A (CLAUDE.md instructions) and Method B (UserPromptSubmit hook) with usage examples, comparison table, and recommended tip callout (Session 82)
🔵 Landing
landing/console.html— Standardized OTP input to 6 digits: updatedplaceholder,maxlength, validation (!== 6), and label to consistently show 6-digit requirement (Session 82)
🔵 Landing
landing/console.html— Fixed plan display bug for users without API keys: whenrenderApiKeysList()early-returns (no keys), now fetches plan from/creditsendpoint as fallback and correctly updates Account tab, SEva file attach button, and TOTP check (Session 82)
🔵 Landing
landing/console.html— Fixed plan showing as "Free" due to browser caching: added?t=Date.now()cache-bust query param to the/api-keysfetch. Root cause: browser returned 304 (Not Modified) with stale cached response (Session 82)landing/console.html— Fixed plan display not updating in Account tab:renderApiKeysList()now callsloadAccountTab()after settingcurrentPlanfrom API keys (keys.length > 0 branch was missing this call) (Session 82)landing/console.html— MadeloadAccountTab()async: whencurrentPlan === 'free'(still loading), it now fetches/api-keysdirectly before rendering, eliminating all timing-dependent "Free" display issues (Session 82)
🟢 Landing
landing/console.html— AddedrefreshSidebarAccess()function. Unlocks Secure RAG sidebar items (🔒→📦 icon, docs link) for Starter+ users after plan is determined. Also centralizes SEva 📎 button control (Session 82)landing/seva/seva.js— Added_attachEnabledinstance variable.setAttachmentEnabled()now persists state so it's correctly applied even if called before DOM is ready (Session 82)
🔵 Proxy + Landing + SEva
proxy/index.js— Unified email resolution in/uploadendpoint to useresolveUserEmail(). Now accepts Supabase JWT (Authorization: Bearer) to identify users, enabling file uploads from the Developer Console (Session 82)proxy/index.js—/uploadplan check now queries bothcreditsandapi_keystables, using whichever shows a higher plan. Fixes case wherecreditsis outdated (free) butapi_keysshows starter (Session 82)landing/seva/seva.js— AddedgetAuthHeaderscallback option._processFileAttachnow includes auth headers in the/uploadfetch (Session 82)landing/console.html— AddedgetAuthHeaders: () => getAuthHeader()to SevaWidget init. Sends Supabase JWT with file upload to pass plan check (Session 82)landing/console.html— ChangedonAuthSuccess()toloadApiKeys().then(() => refreshSidebarAccess()). Sidebar now auto-unlocks after login without requiring Account tab visit (Session 82)landing/console.html— Added plan badge to topbar (topbar-plan-badge). Shows colored badge (Free/Starter/Business/Enterprise) immediately after plan is confirmed. Hidden on logout (Session 82)landing/console.html— AddedinitPlanBadge(): independent plan detection function called on login. Fetches/api-keysdirectly, setscurrentPlan, then callsrefreshSidebarAccess(). Decoupled fromloadApiKeys()list display logic (Session 82)landing/console.html— Added SEvarefreshContext()call insiderefreshSidebarAccess(). Context chip now updates to show correct plan (Session 82)
🔵 Landing
landing/console.html— Fixed all Japanese sample texts in SCENARIOS and PRESETS to use space-separated names (山田太郎 → 山田 太郎, etc.). Affects mask, detect, RAG ingest, and preset scenarios (Session 82)landing/console.html— AddedextraTypes: ["name"]torunRequest()body for Japanese language mode. Console demos now correctly detect and mask Japanese names (Session 82)landing/console.html— Replaced plan gate "View Plans" link with a direct "Upgrade to [Plan]" button. Starter+ features route to Starter Stripe Checkout; Business+ features route to Business Stripe Checkout; Enterprise shows a contact link (Session 82)
🔵 Proxy + Docs
proxy/index.js— AddedrequireStarterPlan()helper function. Unifies plan checking for API key auth (req.apiKey.plan) and Supabase JWT auth (bothcreditsandapi_keystables). Returns 403 for Free plan requests. Reusable middleware for premium endpoints (Session 82)proxy/index.js— AppliedrequireStarterPlan()to/rag/ingestand/rag/resolve. Secure RAG is now restricted to Starter plan and above at the API level (Session 82)docs/ja/api/rag.md/docs/en/api/rag.md— Added "Starter Plan Required" warning callout at page top. Documents the 403 behavior and links to pricing page (Session 82)
🟢 Landing + SEva
landing/seva/seva.js— Fixed file attach button label from "Business" to "Starter+" (both ja/en). File upload is available from Starter plan (Session 82)landing/seva/seva.js—_appendSystemNote()now returns the DOM element._processFileAttach()removes the "Processing file..." message once the review card is displayed (Session 82)landing/seva/seva.js— AddedAbortSignal.timeout(60000)to/uploadfetch. Times out after 60s with error message instead of hanging indefinitely (Session 82)landing/console.html— Addedrag_ingestandrag_resolvetoSCENARIOS. Clicking Secure RAG sidebar items now opens a test panel inside the console instead of attempting to open external docs (Session 82)landing/console.html— Added RAG routing and body construction inrunRequest()forrag_ingest/rag_resolvescenarios (Session 82)landing/console.html— Added RAG response visualization inrenderPreview(): ingest shows chunk list + token count; resolve shows restored text + count (Session 82)
🟡 Landing
landing/console.html— Extended SEva file attachment to Starter plan (📎 button now shown for Starter/Business/Enterprise) (Session 82)landing/seva/seva.js— Added 1 MB file size limit; shows error message in chat if exceeded (Session 82)
🟢 Landing
landing/seva/seva.js+landing/seva/seva.css+landing/console.html— Business/Enterprise Tier file attachment in SEva chat: added 📎 button to chat input (visible for Business/Enterprise plans only). Flow: select file → proxy/upload(text extraction + PII masking) → in-chat review card (PII count, masked preview) → [Send] pushes masked text into SEva. Supported formats: PDF, Word, Excel, PowerPoint, CSV, TXT, MD, HTML, RTF (Session 82)
🔵 Landing
landing/console.html— Fixed TOTP re-enrollment error: automatically unenroll unverified factors before callingmfa.enroll(), eliminating "Failed to get QR code" errors on retry (Session 81)landing/console.html— Fixed TOTP QR code rendering: switched frominnerHTMLtemplate literal tocreateElement+img.srcassignment. Root cause was double quotes inside the data URI breaking the HTML attribute (Session 81)
🟡 Landing
landing/console.html— Account tab: plan-aware action buttons. Free → shows "Upgrade to Starter" and "Upgrade to Business" buttons (direct Stripe Checkout); Starter → shows "Upgrade to Business" button; Business/Enterprise → shows "View Plans" link. Stripe portal button hidden for Free plan users (Session 81)
🟢 Proxy
proxy/index.js— AddedPOST /stripe/create-portal-session. Generates a Stripe Customer Portal URL, enabling the "Open Stripe Portal" button in the Account tab (Session 81)
🟢 Landing
landing/console.html— Account Settings page implemented with 4 tabs: Profile / Security / Activity / Account. API Key management moved from sidebar to Security tab. Profile tab allows setting display name and company name (saved to Supabase user_metadata). Activity tab shows login history and account creation date. Account tab shows plan usage, Stripe billing portal link, and account deletion request. Topbar and org selector now show display name / company name when set (Session 80)landing/console.html— Two-factor authentication (TOTP) implemented: required for Business/Enterprise plans, optional banner for Starter. Login flow adds TOTP challenge as Step 3. Supabase MFA enroll/challenge/verify API integration. QR code display and manual secret key entry supported (Session 80)landing/api-keys.md— Removed plan-tier API call limit table; replaced with link to Plans & Feature Limits page to avoid future sync issues (Session 80)
⚪ Docs
docs/ja/api/quickstart.md— Fixed the quickstart code example: replaced田中太郎(no space, name slipped through) with田中 太郎(space) + addedextraTypes: ["name"]. Example now correctly shows name being masked (Session 80)docs/ja/guide/limitations.md— Added new section honestly documenting the space-required limitation for Japanese name detection, including workarounds and planned improvement (Session 80)docs/en/guide/limitations.md— Added name detection space requirement to English limitations page, including Japanese-specific impact note (Session 80)docs/ja/api/rag.md— Fixed Proxy API example and test result: replaced山田太郎(no space) with山田 太郎(space) + addedextraTypes: ["name"]. Test result updated to show name tokenized correctly (3/3 → 4/4) (Session 80)docs/en/api/rag.md— Updated Proxy API example to useAlice Smith(space) +extraTypes: ["name"]. Test result updated to include name token (Session 80)
🟡 Landing
landing/console.html— Sidebar redesigned (Plan C): restructured into PII Protection / Injection Defense / Secure RAG (Starter+) / Shadow AI (Business+) categories (Session 72)landing/console.html— New endpoints added: POST /detect-sql and POST /detect-all-injections under Injection Defense (Session 72)landing/console.html— New Try It scenarios: SQL Injection and Composite Attack (Session 72)landing/console.html— Plan gate panel: clicking Secure RAG / Shadow AI shows upgrade prompt (Session 72)landing/console.html— EN i18n foundation: I18N object, data-i18n attributes, setLang() extended (Session 72)- Support Chat (
Supportchat/poc/src/server.ts) — SEva Enterprise Privacy Briefing: STEP 0 added before persona selection. SEva asks for company name, division, contact name, and contact info at the start of Enterprise consultations. Declared terms are registered as session-level custom masks and applied viaextractDeclaredPII()+maskWithCustomTerms()before writing to seva_logs — company names and contact PII are never stored in plain text (Session 77) landing/seva/seva.js+landing/console.html— Prospect tracking:userId(Supabase UUID) andendpointsTriedadded to SEva context; forwarded to Railway for purchase-intent scoring (Session 76)landing/seva/seva.js+landing/console.html— SEva default open: panel opens automatically on console load (defaultOpen: true); users can hide via tab button (Session 76)landing/seva/seva.js— SalesEva: addedcallsUsedandcallLimitto server context note, enabling usage-based upgrade nudges in SYSTEM_PROMPT (Session 76)landing/seva/seva.js+landing/seva/seva.css— SEva feedback button layout fix: buttons now appear BELOW the chat bubble (column layout via.seva-bub-wrapwrapper) instead of to the right (Session 75)landing/seva/seva.js+landing/seva/seva.css— SEva Learning Loop Phase 3: 👍/👎 feedback buttons added to bot messages._rate()method (fire-and-forget to chatUrl/rate). JA/EN i18n support (Session 74)app/src/main.jsx— Terms of Service agreement screen added: version-based consent (TERMS_VER),terms_agreementsSupabase table check, re-consent on version update (Session 74)landing/console.html— OTP input: maxlength changed from 6 to 8; label updated to "確認コード(6〜8桁)" (Supabase sends 8-digit codes in some cases) (Session 73)landing/seva/seva.js+landing/seva/seva.css— SEva (SupportEva) Phase 1: AI technical support widget as standalone reusable module (SevaWidget class); right-side 340px slide panel, Railway chat API connection, Privacy by Design context passing, JA/EN i18n (Session 73)docs/en/api/seva.md+docs/ja/api/seva.md— SEva documentation: overview, Privacy by Design principles, FAQ, example questions; added to sidebar under Infrastructure & Operations (Session 73)landing/console.html— SEva contextFn complete: added endpointsTried (visited endpoint history, dedup, max 10), callsUsed (monthly total across all keys), callLimit (plan limit); all three are behavioral metadata only — Privacy by Design boundary maintained (Session 73)landing/seva/seva.js— SEva Phase 2: full PII Firewall pipeline on every message (detectAllInjections → mask → Railway chat → restore-text); attack blocking with counter, PII mask count display, graceful degradation on pipeline errors (Session 73)docs/en/api/seva.md+docs/ja/api/seva.md— Enriched SEva docs: full pipeline diagram (detectAllInjections → mask → Secure RAG → Claude → restoreAll), Secure RAG knowledge base architecture, real-time protection stats explanation, expanded FAQ and question examples (Session 73)landing/tokusho.html— Phone number updated from "pending" to070-3630-6741(JA/EN); removed "pending" note (Session 71)landing/index.html— All nav items (Products, Solutions, Developers, Resources, Pricing, Sign In) fully disabled viapointer-events:none; opacity:0.45; cursor:default; Sign In also getsonclick="return false"during patent application period (Session 71)
🔵 Infrastructure & Security (Session 71)
- 2FA enabled on all services: GitHub (Passkey+TOTP+Recovery), Cloudflare (TOTP+Backup), Supabase (App 278), Railway (App+Recovery) (Session 71)
- Vercel account deleted; GitHub Apps cleaned up (Cloudflare + Railway only) (Session 71)
- Supabase Pro upgrade (M-DEEP inc corporate billing; daily auto-backup 7-day retention) (Session 71)
- Cloudflare Email Routing updated: support@piifirewall.com → support@m-deep.com (Active) (Session 71)
⚪ Docs (Session 71)
internal-docs/infra/account-migration.md— Added 2FA completion status, GitHub Apps cleanup, Cloudflare security plan, Email Routing, and Google Workspace configuration sections (Session 71)internal-docs/project/tips.md— Added Markdown → Word conversion section (Session 71)/md-to-wordskill created (C:\Users\kmish\.claude\commands\md-to-word.md) (Session 71)landing/index.html— Simplified to general-user view for patent application preparation (Session 70): all nav dropdowns hidden, audience section hidden, MCP callout hidden, Developer section hidden, Pricing section hidden, contact form hidden, chat widget hidden, CTA buttons disabled (all viadisplay:none/pointer-events:none, instantly reversible)landing/index-v2.html— Secure RAG section removed (patent pending, not for public disclosure) (Session 67)landing/index-v2.html— Purchase flow fix applied: Start Starter/Business → OTP → redirect with?plan=param → Stripe Checkout auto-launch (Session 67)landing/index-v2.html— Added missing auth modal HTML (was causing null classList error on Start Starter click) (Session 67)landing/portal.html— Added Stripe Checkout auto-launch on?plan=starter|businessURL param after OTP redirect (Session 67)landing/index.html/index-v2.html— Fixed Magic LinkemailRedirectToto include plan params (plan was lost when Supabase redirected via Site URL) (Session 67)landing/index-v2.html— Secure RAG section changed from deleted todisplay:none(can be re-enabled after patent filing) (Session 67)landing/index.html/index-v2.html— Fixed OTP form: changed 8-char check to 6-char minimum (Supabase sends 6-digit codes but form was blocking on 8-char requirement) (Session 67)landing/portal.html— Fixed Stripe Checkout: changedwindow.opentowindow.location.hrefto bypass popup blocker (Session 67)
🔵 Fixed
landing/console.html— Added "Last Used" column to API key list (last_used_at; shows "—" for unused keys) (Session 69)proxy/api-key-auth.js— API call usage is now aggregated per user (sum across all keys). Monthly call count is preserved on key rotation or new key creation (Session 69)proxy/api-key-auth.js— Fixed broken.rpcreference in Enterprise plan call logging code (Session 69)landing/index.html/index-v2.html— OTP redirect target changed from/portalto/console(5/1 release is developer-facing; portal is not linked) (Session 68)landing/console.html— Fixed POST /detect Preview showing "No PII Detected" even when detections exist (/detectreturnscandidatesarray, notdetections) (Session 68)landing/console.html— Added Stripe Checkout auto-launch on?plan=param after OTP redirect from landing (Session 68)landing/console.html— Removedapp.piifirewall.comreference in login overlay (app not released until 5/1) (Session 68)landing/console.html— Org name and SANDBOX/LIVE badge now dynamically update on login/logout (was hardcoded "Acme Corp" / "SANDBOX") (Session 68)landing/console.html— API key list now shows monthly call usage: Free showscalls / 300with progress bar and color warning (yellow ≥70%, red ≥90%); Starter/Business shows raw call count (Session 68)proxy/index.js— CORS: addedpii-firewall.pages.devto allowed origins (Cloudflare Pages preview URLs use hyphen, notpiifirewall.com, causing Stripe session fetch to be blocked) (Session 67)- Purchase flow: Fixed "Start Starter/Business" → OTP → Stripe Checkout not launching; now auto-triggers checkout after OTP verification (Session 66)
- Updated
@xmldom/xmldomfrom 0.8.11 → 0.9.10 (High: XML injection vulnerability GHSA-wh4c-j3r5-mjhp) (Session 66) - Updated
dompurifyfrom 3.3.3 → 3.4.0 (Moderate: ADD_TAGS bypass vulnerability GHSA-39q2-94rc-95cp) (Session 66)
🟢 Added
examples/ollama-basic.js— PII Firewall + Ollama basic integration sample (mask → send → restore) (Session 62)examples/ollama-secure-rag.js— Secure RAG + Ollama sample (use internal documents with local LLM) (Session 62)examples/ollama-full-defense.js— Full defense pipeline sample (composite attack detection + PII protection + Ollama) (Session 62)examples/README.md— Ollama integration samples setup & run guide (Session 62)fw.detectAllInjections(text, lang?)— Composite attack detection: detects SQL injection and prompt injection simultaneously; returns{ hasSQLInjection, hasPromptInjection, compositeRisk }(Session 58)fw.detectSQLInjection(text)— Standalone SQL injection detection (Session 58)rag_ingestMCP tool — Tokenizes PII in documents for Secure RAG pipelines; returns chunked, anonymized text (Session 59)rag_resolveMCP tool — Restores SRAG tokens in LLM responses to original values (Session 59)- MCP Server now has 9 tools (was 6): added
detect_all_injections,rag_ingest,rag_resolve - API key detection expanded to 11 providers: Anthropic, OpenAI, Stripe, Google AI (AIzaSy…), HuggingFace (hf_), Groq (gsk_), Perplexity (pplx-), Replicate (r8_), AWS (AKIA…), GitHub (ghp_, ghs_, github_pat_) (Session 59)
POST /maskProxy API endpoint — Masks all PII in text and returns{ masked, detections }. Designed for external SDKs and AI agents (Session 64)POST /restore-textProxy API endpoint — Restores SECURED tokens in bulk and returns the restored text. Agent-oriented alternative to/restore-all(Session 64)/detect-all-injectionsProxy API endpoint — HTTP endpoint for composite attack detection (Session 58)/rag/ingestand/rag/resolveProxy API endpoints (Session 58)- Enterprise deployment pattern docs: CLAUDE.md + Claude for Teams Projects system prompt enforcement (Session 59)
🟡 Landing
- All nav: "ソリューション" renamed to "選ぶ理由" / "Why PII Firewall" across all 14 pages (Session 61)
landing/solutions/injection-defense.html— Added SQL Injection section, competitive comparison table, updated Hero (Session 61)landing/index-v2.html— UX improvements (9 items): tab button resize, step arrows in How section, larger Secure RAG flow, Pricing center-align, section-desc centering fix, punctuation cleanup (Session 61)landing/index-v2.html— Developer-first full redesign: 8-section structure (Code/HowItWorks/Integrations/Capabilities/RAG/Pricing/Trust/CTA), npm install primary CTA, browser-app CTAs removed, heading punctuation rules established (Session 61)landing/index-v2.html— Hero message redesign: "Ship AI to production. Overcome the last mile with one line of code." (Session 60)
⚪ Docs
internal-docs/sessions/— Session 59/60/61 reports and handoff documents added to sessions index (Session 61)en/api/rag.md— New standalone Secure RAG page split from mcp.md (Session 62)en/api/injection-detection.md— New standalone Composite Attack Detection page split from mcp.md (Session 62)en/api/mcp.md— Trimmed to MCP Server core; cross-links added to Secure RAG and Composite Attack Detection pages (Session 62)en/api/index.md— Overview updated: 5 integration options, 7 key capabilities, API key not required note for MCP/SDK (Session 62)docs/.vitepress/config.ts— JA/EN sidebars reorganized into category groups (Getting Started / Integration / Reference / Implementation Guides / Infrastructure) (Session 62)
⚪ Docs
en/api/use-cases.md— Use Cases by Industry guide (Finance, Legal, Healthcare, Manufacturing, Enterprise) (Session 59)ja/api/use-cases.md— 業種別導入事例ガイド + Manufacturing Secure RAG + Enterprise deployment patterns (Session 59)en/api/slack-it-integration.md— Slack & IT/OT System Integration Guide (MCP system prompt + Proxy API patterns) (Session 59)ja/api/slack-it-integration.md— Slack・IT/OT連携ガイド (Session 59)en/api/mcp.md/ja/api/mcp.md— Updated for 9 tools, added Secure RAG pipeline section, API key detection table (Session 59)en/api/sdk.md/ja/api/core-functions.md— AddeddetectAllInjections()with competitor comparison table (Session 59)- Shadow AI monitoring docs added (Session 55–56)
🟡 Changed
- MCP Server tool count: 6 → 9
v0.1.0 — 2026-04-13
Added
@pii-firewall/core— 24 PII types, mask/restore, differential privacy, injection detection (10 categories)@pii-firewall/sdk— Node.js SDK (createFirewall(),maskPII(),detectPII(),detectInjection())@pii-firewall/mcp-server— MCP Server for Claude Desktop / Cursor (6 tools)- REST API —
/detect,/mask,/restore,/detect-injectionendpoints - Developer Console —
piifirewall.com/console(email OTP auth, API key issuance & management) - API key authentication —
pf_live_xxxformat with plan-based call limits
Language support
- Japanese (
lang: "ja") and English (lang: "en")
Infrastructure
- Railway (proxy) · Cloudflare Pages (landing) · Cloudflare Workers (app, docs)
Changelog conventions
| Type | Description |
|---|---|
| 🔴 Breaking | Breaking API changes (response format, endpoint removal) |
| 🟢 Added | New features or endpoints |
| 🟡 Changed | Changes to existing features |
| 🔵 Fixed | Bug fixes |
| ⚪ Docs | Documentation-only changes |