mega-brain-ai 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mega-brain-ai might be problematic. Click here for more details.
- package/.claude/CLAUDE.md +155 -0
- package/.claude/commands/agents.md +161 -0
- package/.claude/commands/ask.md +117 -0
- package/.claude/commands/benchmark.md +224 -0
- package/.claude/commands/chat.md +343 -0
- package/.claude/commands/compare.md +116 -0
- package/.claude/commands/conclave.md +194 -0
- package/.claude/commands/config.md +133 -0
- package/.claude/commands/council.md +194 -0
- package/.claude/commands/create-agent.md +452 -0
- package/.claude/commands/debate.md +157 -0
- package/.claude/commands/documentation/create-architecture-documentation.md +175 -0
- package/.claude/commands/dossiers.md +180 -0
- package/.claude/commands/evolve.md +223 -0
- package/.claude/commands/extract-dna.md +170 -0
- package/.claude/commands/extract-knowledge.md +507 -0
- package/.claude/commands/inbox.md +296 -0
- package/.claude/commands/ingest-empresa.md +191 -0
- package/.claude/commands/ingest.md +182 -0
- package/.claude/commands/jarvis-briefing.md +67 -0
- package/.claude/commands/jarvis-control.md +169 -0
- package/.claude/commands/jarvis-full.md +181 -0
- package/.claude/commands/jarvis.md +212 -0
- package/.claude/commands/ler-drive.md +212 -0
- package/.claude/commands/log.md +158 -0
- package/.claude/commands/loop.md +133 -0
- package/.claude/commands/loops.md +73 -0
- package/.claude/commands/mission-autopilot.md +538 -0
- package/.claude/commands/mission.md +353 -0
- package/.claude/commands/process-inbox.md +148 -0
- package/.claude/commands/process-jarvis.md +3036 -0
- package/.claude/commands/process-video.md +131 -0
- package/.claude/commands/rag-search.md +78 -0
- package/.claude/commands/resume.md +33 -0
- package/.claude/commands/save.md +38 -0
- package/.claude/commands/scan-inbox.md +125 -0
- package/.claude/commands/setup.md +99 -0
- package/.claude/commands/system-digest.md +243 -0
- package/.claude/commands/verify.md +182 -0
- package/.claude/commands/view-dna.md +169 -0
- package/.claude/hooks/agent_doctor.py +433 -0
- package/.claude/hooks/agent_memory_persister.py +203 -0
- package/.claude/hooks/auto_formatter.py +158 -0
- package/.claude/hooks/checkpoint_writer.py +244 -0
- package/.claude/hooks/claude_md_guard.py +146 -0
- package/.claude/hooks/creation_validator.py +357 -0
- package/.claude/hooks/enforce_dual_location.py +501 -0
- package/.claude/hooks/enforce_plan_mode.py +220 -0
- package/.claude/hooks/inbox_age_alert.py +367 -0
- package/.claude/hooks/jarvis_briefing.py +506 -0
- package/.claude/hooks/ledger_updater.py +301 -0
- package/.claude/hooks/memory_hints_injector.py +251 -0
- package/.claude/hooks/memory_updater.py +202 -0
- package/.claude/hooks/multi_agent_hook.py +464 -0
- package/.claude/hooks/notification_system.py +120 -0
- package/.claude/hooks/pattern_analyzer.py +526 -0
- package/.claude/hooks/pending_tracker.py +188 -0
- package/.claude/hooks/post_batch_cascading.py +1740 -0
- package/.claude/hooks/post_output_validator.py +358 -0
- package/.claude/hooks/post_tool_use.py +120 -0
- package/.claude/hooks/post_write_validator.py +200 -0
- package/.claude/hooks/quality_watchdog.py +394 -0
- package/.claude/hooks/ralph_wiggum.py +277 -0
- package/.claude/hooks/session-source-sync.py +218 -0
- package/.claude/hooks/session_autosave_v2.py +1135 -0
- package/.claude/hooks/session_end.py +203 -0
- package/.claude/hooks/session_start.py +939 -0
- package/.claude/hooks/skill_indexer.py +48 -0
- package/.claude/hooks/skill_router.py +358 -0
- package/.claude/hooks/stop_hook_completeness.py +178 -0
- package/.claude/hooks/subagent_tracker.py +163 -0
- package/.claude/hooks/token_checkpoint.py +584 -0
- package/.claude/hooks/user_prompt_submit.py +125 -0
- package/.claude/rules/ANTHROPIC-STANDARDS.md +384 -0
- package/.claude/rules/CLAUDE-LITE.md +201 -0
- package/.claude/rules/RULE-GROUP-1.md +320 -0
- package/.claude/rules/RULE-GROUP-2.md +307 -0
- package/.claude/rules/RULE-GROUP-3.md +248 -0
- package/.claude/rules/RULE-GROUP-4.md +427 -0
- package/.claude/rules/RULE-GROUP-5.md +388 -0
- package/.claude/rules/RULE-GROUP-6.md +387 -0
- package/.claude/rules/logging.md +53 -0
- package/.claude/rules/mcp-governance.md +128 -0
- package/.claude/rules/pipeline.md +60 -0
- package/.claude/rules/state-management.md +93 -0
- package/.claude/scripts/apply-tags.py +77 -0
- package/.claude/scripts/batch-extract-transcriptions.py +132 -0
- package/.claude/scripts/build-complete-index.py +250 -0
- package/.claude/scripts/build-planilha-index.py +170 -0
- package/.claude/scripts/complete-tag-matching.py +250 -0
- package/.claude/scripts/deduplicate-inbox.py +139 -0
- package/.claude/scripts/docx-xml-extractor.py +141 -0
- package/.claude/scripts/extract-docx-text.py +58 -0
- package/.claude/scripts/extract-single-transcription.py +74 -0
- package/.claude/scripts/extract_docx_from_gdrive.py +77 -0
- package/.claude/scripts/organized-downloader.py +246 -0
- package/.claude/scripts/planilha-tagger.py +187 -0
- package/.claude/scripts/revert-tags.py +70 -0
- package/.claude/scripts/source-sync.py +265 -0
- package/.claude/scripts/tag-inbox-files.py +276 -0
- package/.claude/scripts/tag-inbox-v2.py +253 -0
- package/.claude/scripts/test-extraction.py +35 -0
- package/.claude/scripts/test-full-extraction.py +74 -0
- package/.claude/skills/00-SKILL-CREATOR/SKILL.md +186 -0
- package/.claude/skills/01-SKILL-DOCS-MEGABRAIN/SKILL.md +251 -0
- package/.claude/skills/02-SKILL-PYTHON-MEGABRAIN/SKILL.md +323 -0
- package/.claude/skills/03-SKILL-AGENT-CREATION/SKILL.md +374 -0
- package/.claude/skills/04-SKILL-KNOWLEDGE-EXTRACTION/SKILL.md +318 -0
- package/.claude/skills/05-SKILL-PIPELINE-JARVIS/SKILL.md +430 -0
- package/.claude/skills/06-SKILL-BRAINSTORMING/SKILL.md +72 -0
- package/.claude/skills/07-SKILL-DISPATCHING-PARALLEL-AGENTS/SKILL.md +193 -0
- package/.claude/skills/08-SKILL-EXECUTING-PLANS/SKILL.md +114 -0
- package/.claude/skills/09-SKILL-WRITING-PLANS/SKILL.md +184 -0
- package/.claude/skills/10-SKILL-VERIFICATION-BEFORE-COMPLETION/SKILL.md +130 -0
- package/.claude/skills/11-SKILL-USING-SUPERPOWERS/SKILL.md +105 -0
- package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
- package/.claude/skills/README.md +240 -0
- package/.claude/skills/SKILL-REGISTRY.md +284 -0
- package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
- package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
- package/.claude/skills/chronicler/SKILL.md +146 -0
- package/.claude/skills/chronicler/chronicler_core.py +468 -0
- package/.claude/skills/code-review/SKILL.md +160 -0
- package/.claude/skills/council/SKILL.md +210 -0
- package/.claude/skills/executor/SKILL.md +161 -0
- package/.claude/skills/fase-2-5-tagging/SKILL.md +182 -0
- package/.claude/skills/feature-dev/SKILL.md +154 -0
- package/.claude/skills/finance-agent/SKILL.md +137 -0
- package/.claude/skills/frontend-design/SKILL.md +165 -0
- package/.claude/skills/gdrive-transcription-downloader/SKILL.md +249 -0
- package/.claude/skills/gemini-fallback/SKILL.md +67 -0
- package/.claude/skills/gemini-fallback/gemini_fetch.py +0 -0
- package/.claude/skills/gha/SKILL.md +96 -0
- package/.claude/skills/gha/gha_diagnostic.py +227 -0
- package/.claude/skills/github-workflow/SKILL.md +190 -0
- package/.claude/skills/hookify/SKILL.md +134 -0
- package/.claude/skills/hybrid-source-reading/SKILL.md +265 -0
- package/.claude/skills/jarvis/SKILL.md +546 -0
- package/.claude/skills/jarvis-briefing/SKILL.md +340 -0
- package/.claude/skills/ler-planilha/SKILL.md +281 -0
- package/.claude/skills/plugin-dev/SKILL.md +176 -0
- package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
- package/.claude/skills/resume/SKILL.md +61 -0
- package/.claude/skills/save/SKILL.md +87 -0
- package/.claude/skills/skill-writer/SKILL.md +153 -0
- package/.claude/skills/skill-writer/examples.md +191 -0
- package/.claude/skills/skill-writer/troubleshooting.md +205 -0
- package/.claude/skills/smart-download-tagger/SKILL.md +148 -0
- package/.claude/skills/source-sync/SKILL.md +240 -0
- package/.claude/skills/sync-docs/SKILL.md +193 -0
- package/.claude/skills/sync-docs/config.json +37 -0
- package/.claude/skills/sync-docs/gdrive_sync.py +358 -0
- package/.claude/skills/sync-docs/reauth.py +71 -0
- package/.claude/skills/talent-agent/SKILL.md +183 -0
- package/.claude/skills/verify/SKILL.md +154 -0
- package/.claude/skills/verify/verify_runner.py +0 -0
- package/.claude/skills/verify-6-levels/SKILL.md +234 -0
- package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
- package/.claudeignore +9 -0
- package/.gitattributes +4 -0
- package/.github/layer1-allowlist.txt +80 -0
- package/.github/layer2-manifest.txt +40 -0
- package/.gitignore +219 -0
- package/README.md +1210 -0
- package/agents/_templates/INDEX.md +741 -0
- package/agents/_templates/TEMPLATE-AGENT-MD-ULTRA-ROBUSTO-V3.md +2399 -0
- package/agents/boardroom/CHECKLIST-MASTER.md +281 -0
- package/agents/boardroom/INTEGRATION-GUIDE.md +406 -0
- package/agents/boardroom/README.md +238 -0
- package/agents/boardroom/config/BOARDROOM-CONFIG.md +186 -0
- package/agents/boardroom/config/TTS-INTEGRATION.md +258 -0
- package/agents/boardroom/config/VOICE-PROFILES.md +624 -0
- package/agents/boardroom/config/voice_mapping.json +128 -0
- package/agents/boardroom/scripts/audio_generator.py +375 -0
- package/agents/boardroom/scripts/audio_generator_edge.py +353 -0
- package/agents/boardroom/scripts/jarvis_boardroom_hook.py +415 -0
- package/agents/boardroom/scripts/notebooklm_generator.py +578 -0
- package/agents/boardroom/templates/EPISODE-TEMPLATE.md +367 -0
- package/agents/boardroom/templates/scene-templates/SCENE-AGENT-DEBATE.md +252 -0
- package/agents/boardroom/templates/scene-templates/SCENE-COUNCIL.md +270 -0
- package/agents/boardroom/templates/scene-templates/SCENE-DNA-CONSULTATION.md +126 -0
- package/agents/boardroom/templates/scene-templates/SCENE-QUESTION.md +174 -0
- package/agents/boardroom/workflows/WORKFLOW-AUDIO-GENERATION.md +421 -0
- package/agents/constitution/BASE-CONSTITUTION.md +254 -0
- package/agents/council/CRITIC.md +197 -0
- package/agents/council/DEVILS-ADVOCATE.md +274 -0
- package/agents/council/SYNTHESIZER.md +293 -0
- package/agents/council/advogado-do-diabo/AGENT.md +489 -0
- package/agents/council/advogado-do-diabo/SOUL.md +100 -0
- package/agents/council/critico-metodologico/AGENT.md +670 -0
- package/agents/council/critico-metodologico/SOUL.md +107 -0
- package/agents/council/sintetizador/AGENT.md +558 -0
- package/agents/council/sintetizador/SOUL.md +94 -0
- package/agents/persons/_example/AGENT-EXAMPLE.md +42 -0
- package/agents/persons/_example/DNA-EXAMPLE.yaml +61 -0
- package/agents/protocols/AGENT-COGNITION-PROTOCOL.md +779 -0
- package/agents/protocols/AGENT-INTEGRITY-PROTOCOL.md +692 -0
- package/agents/protocols/BATCH-VISUAL-PROTOCOL.md +841 -0
- package/agents/protocols/DNA-CONFIG-TEMPLATE.yaml +181 -0
- package/agents/protocols/DNA-EXTRACTION-PROTOCOL.md +370 -0
- package/agents/protocols/EPISTEMIC-PROTOCOL.md +333 -0
- package/agents/protocols/LOG-STRUCTURE-PROTOCOL.md +65 -0
- package/agents/protocols/MEMORY-PROTOCOL.md +567 -0
- package/agents/protocols/NARRATIVE-SYNTHESIS-PROTOCOL.md +278 -0
- package/agents/protocols/PHASE-4-VERIFICATION-CHECKPOINT.md +146 -0
- package/agents/protocols/SOUL-TEMPLATE.md +416 -0
- package/agents/protocols/TEMPLATE-EVOLUTION-PROTOCOL.md +544 -0
- package/agents/protocols/VISUAL-DIFF-PROTOCOL.md +159 -0
- package/agents/sua-empresa/README.md +44 -0
- package/agents/sua-empresa/_example/jds/EXAMPLE-JD.md +42 -0
- package/agents/sua-empresa/_example/org/EXAMPLE-ORG.md +32 -0
- package/agents/sua-empresa/_example/roles/EXAMPLE-ROLE.md +38 -0
- package/bin/cli.js +2 -0
- package/bin/lib/ascii-art.js +234 -0
- package/bin/lib/installer.js +402 -0
- package/bin/lib/setup-wizard.js +95 -0
- package/bin/lib/validate-email.js +109 -0
- package/bin/mega-brain.js +97 -0
- package/bin/push.js +342 -0
- package/bin/templates/env.example +38 -0
- package/inbox/.gitkeep +0 -0
- package/integrations/README.md +46 -0
- package/integrations/mcps/MCP-REGISTRY.md +56 -0
- package/integrations/mcps/excalidraw/CONFIG.md +56 -0
- package/integrations/mcps/gdrive/CONFIG.md +38 -0
- package/knowledge/dna/.gitkeep +0 -0
- package/knowledge/dossiers/persons/.gitkeep +0 -0
- package/knowledge/dossiers/persons/DOSSIER-EXAMPLE.md +49 -0
- package/knowledge/dossiers/system/.gitkeep +0 -0
- package/knowledge/dossiers/themes/.gitkeep +0 -0
- package/knowledge/playbooks/.gitkeep +0 -0
- package/knowledge/playbooks/PLAYBOOK-EXAMPLE.md +50 -0
- package/knowledge/sources/.gitkeep +0 -0
- package/logs/.gitkeep +0 -0
- package/package.json +128 -0
- package/processing/canonical/.gitkeep +0 -0
- package/processing/chunks/.gitkeep +0 -0
- package/processing/insights/.gitkeep +0 -0
- package/processing/narratives/.gitkeep +0 -0
- package/reference/CONSELHO.md +337 -0
- package/reference/CONTEXT7_README.md +28 -0
- package/reference/JARVIS-LOGGING-PROTOCOL.md +380 -0
- package/reference/QUICK-START.md +197 -0
- package/reference/README-RALPH-CASCATEAMENTO.md +207 -0
- package/reference/TEMPLATE-MASTER.md +727 -0
- package/reference/prds/prd-jarvis-mega-brain-v3.md +1305 -0
- package/reference/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
- package/reference/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
- package/reference/templates/phase5/README.md +165 -0
- package/reference/workflow-claude-code-boris-cherny-continuous-claude.md +2232 -0
- package/system/database/001_moneyclub_buyers.sql +160 -0
- package/system/database/002_premium_token.sql +97 -0
- package/system/database/apply-migration.mjs +129 -0
- package/system/docs/MEGA-BRAIN-DEMO-COMPLETA.md +1226 -0
- package/system/docs/MEGA-BRAIN-MANIFESTO-COMPLETO.md +1054 -0
- package/system/docs/MOGA-BRAIN-EXPLICACAO-COMPLETA.md +791 -0
- package/system/docs/STRATEGIC-INTEGRATION-GUIDE.md +725 -0
- package/system/docs/architecture/01-system-context.md +136 -0
- package/system/docs/architecture/02-components.md +225 -0
- package/system/docs/architecture/03-data-flow.md +235 -0
- package/system/docs/architecture/04-integrations.md +283 -0
- package/system/docs/architecture/README.md +71 -0
- package/system/docs/architecture/diagrams/component-diagram.mmd +50 -0
- package/system/docs/architecture/diagrams/data-flow.mmd +39 -0
- package/system/docs/architecture/diagrams/system-overview.mmd +68 -0
- package/system/protocols/AGENT-AUTHORITY.md +217 -0
- package/system/protocols/CONSTITUICAO-BASE.md +115 -0
- package/system/protocols/CONSTITUTION.md +231 -0
- package/system/protocols/GOVERNANCE-MAP.md +123 -0
- package/system/protocols/HOOK-SECURITY-THREAT-MODEL.md +152 -0
- package/system/protocols/ORQUESTRACAO-PROTOCOL.md +215 -0
- package/system/protocols/_archive/CHUNKING-PROTOCOL.md +207 -0
- package/system/protocols/_archive/ENTITY-RESOLUTION-PROTOCOL.md +269 -0
- package/system/protocols/_archive/INSIGHT-EXTRACTION-PROTOCOL.md +257 -0
- package/system/protocols/_archive/NARRATIVE-SYNTHESIS-PROTOCOL.md +290 -0
- package/system/protocols/agents/AGENT-INTERACTION.md +315 -0
- package/system/protocols/agents/CORTEX-PROTOCOL.md +520 -0
- package/system/protocols/agents/EPISTEMIC-PROTOCOL.md +465 -0
- package/system/protocols/agents/MEMORY-PROTOCOL.md +366 -0
- package/system/protocols/agents/WAR-ROOM.md +355 -0
- package/system/protocols/company/COMPANY-DOCUMENT-PROTOCOL.md +793 -0
- package/system/protocols/company/COMPANY-ENRICHMENT-PROTOCOL.md +679 -0
- package/system/protocols/conclave/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/conclave/CONCLAVE-PROTOCOL.md +518 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/conclave/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/council/COUNCIL-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/council/COUNCIL-PROTOCOL.md +518 -0
- package/system/protocols/council/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/council/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/council/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/dna/DNA-EXTRACTION-PROTOCOL.md +1214 -0
- package/system/protocols/dna/ENRICHMENT-PROTOCOL.md +408 -0
- package/system/protocols/dna/REASONING-MODEL-PROTOCOL.md +331 -0
- package/system/protocols/pipeline/DOSSIER-COMPILATION-PROTOCOL.md +790 -0
- package/system/protocols/pipeline/NARRATIVE-METABOLISM-PROTOCOL.md +292 -0
- package/system/protocols/pipeline/PIPELINE-JARVIS-v2.1.md +606 -0
- package/system/protocols/pipeline/PROMPT-1.1-CHUNKING.md +154 -0
- package/system/protocols/pipeline/PROMPT-1.2-ENTITY-RESOLUTION.md +186 -0
- package/system/protocols/pipeline/PROMPT-2.1-DNA-TAGS-INCREMENT.md +208 -0
- package/system/protocols/pipeline/PROMPT-2.1-INSIGHT-EXTRACTION.md +191 -0
- package/system/protocols/pipeline/PROMPT-3.1-NARRATIVE-SYNTHESIS.md +331 -0
- package/system/protocols/pipeline/SOURCES-COMPILATION-PROTOCOL.md +340 -0
- package/system/protocols/system/AUTO-LOG-PROTOCOL.md +369 -0
- package/system/protocols/system/CHECKPOINT-ENFORCEMENT.md +176 -0
- package/system/protocols/system/ENFORCEMENT.md +435 -0
- package/system/protocols/system/LOG-TEMPLATES.md +1068 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
-- Migration: 001_moneyclub_buyers
|
|
2
|
+
-- Description: MoneyClub buyers table for email validation during Mega Brain installation
|
|
3
|
+
-- Date: 2026-02-18
|
|
4
|
+
-- Product: Mega Brain - MoneyClub Edition
|
|
5
|
+
--
|
|
6
|
+
-- DATA FLOW:
|
|
7
|
+
-- Google Sheets (source) → Sync (n8n/Apps Script) → Supabase (source of truth) → CLI validator
|
|
8
|
+
--
|
|
9
|
+
-- SPREADSHEET COLUMNS:
|
|
10
|
+
-- Nome do Cliente | E-mail do Cliente | DDI | DDD | Número do Telefone | Telefone Completo
|
|
11
|
+
--
|
|
12
|
+
-- SYNC STRATEGY:
|
|
13
|
+
-- The Google Sheet is the data entry point (updated by sales team).
|
|
14
|
+
-- A sync mechanism (n8n workflow or Google Apps Script) upserts rows
|
|
15
|
+
-- into this table using email as the unique key.
|
|
16
|
+
-- The CLI installer calls validate_buyer_email() via Supabase anon RPC.
|
|
17
|
+
|
|
18
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
19
|
+
-- TABLE: moneyclub_buyers
|
|
20
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS moneyclub_buyers (
|
|
23
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
24
|
+
|
|
25
|
+
-- From Google Sheets
|
|
26
|
+
name TEXT, -- "Nome do Cliente"
|
|
27
|
+
email TEXT NOT NULL UNIQUE, -- "E-mail do Cliente" (VALIDATOR KEY)
|
|
28
|
+
phone_ddi TEXT, -- "DDI do Cliente" (ex: +55)
|
|
29
|
+
phone_ddd TEXT, -- "DDD do Cliente" (ex: 11)
|
|
30
|
+
phone_number TEXT, -- "Número do Telefone do Cliente"
|
|
31
|
+
phone_full TEXT, -- "Telefone Completo do Cliente"
|
|
32
|
+
|
|
33
|
+
-- Installer tracking (managed by RPC function)
|
|
34
|
+
product TEXT NOT NULL DEFAULT 'moneyclub',
|
|
35
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'refunded')),
|
|
36
|
+
activated_at TIMESTAMPTZ, -- First install timestamp
|
|
37
|
+
install_count INTEGER DEFAULT 0, -- How many times installed
|
|
38
|
+
last_install_at TIMESTAMPTZ, -- Last install timestamp
|
|
39
|
+
|
|
40
|
+
-- Metadata
|
|
41
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
42
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
-- Index for fast email lookup (used by RPC function)
|
|
46
|
+
CREATE INDEX IF NOT EXISTS idx_moneyclub_buyers_email ON moneyclub_buyers(email);
|
|
47
|
+
|
|
48
|
+
-- Index for status filtering
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_moneyclub_buyers_status ON moneyclub_buyers(status);
|
|
50
|
+
|
|
51
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
52
|
+
-- ROW LEVEL SECURITY
|
|
53
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
54
|
+
-- No direct access for anon role. All access goes through the RPC function.
|
|
55
|
+
|
|
56
|
+
ALTER TABLE moneyclub_buyers ENABLE ROW LEVEL SECURITY;
|
|
57
|
+
|
|
58
|
+
-- Service role can do everything (for sync scripts)
|
|
59
|
+
CREATE POLICY "service_role_full_access" ON moneyclub_buyers
|
|
60
|
+
FOR ALL
|
|
61
|
+
TO service_role
|
|
62
|
+
USING (true)
|
|
63
|
+
WITH CHECK (true);
|
|
64
|
+
|
|
65
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
66
|
+
-- RPC FUNCTION: validate_buyer_email
|
|
67
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
68
|
+
-- Called by the CLI installer (npx mega-brain install)
|
|
69
|
+
-- Uses SECURITY DEFINER so anon key can access the table safely
|
|
70
|
+
-- Only returns: valid (bool), name (string), install_count (int)
|
|
71
|
+
-- Never exposes: phone, email list, or other buyer data
|
|
72
|
+
|
|
73
|
+
CREATE OR REPLACE FUNCTION validate_buyer_email(buyer_email TEXT)
|
|
74
|
+
RETURNS JSON
|
|
75
|
+
LANGUAGE plpgsql
|
|
76
|
+
SECURITY DEFINER
|
|
77
|
+
AS $$
|
|
78
|
+
DECLARE
|
|
79
|
+
buyer RECORD;
|
|
80
|
+
BEGIN
|
|
81
|
+
SELECT id, email, name, status, install_count
|
|
82
|
+
INTO buyer
|
|
83
|
+
FROM moneyclub_buyers
|
|
84
|
+
WHERE LOWER(email) = LOWER(buyer_email)
|
|
85
|
+
AND status = 'active';
|
|
86
|
+
|
|
87
|
+
IF buyer IS NULL THEN
|
|
88
|
+
RETURN json_build_object(
|
|
89
|
+
'valid', false,
|
|
90
|
+
'reason', 'email_not_found'
|
|
91
|
+
);
|
|
92
|
+
END IF;
|
|
93
|
+
|
|
94
|
+
-- Update install tracking
|
|
95
|
+
UPDATE moneyclub_buyers
|
|
96
|
+
SET install_count = install_count + 1,
|
|
97
|
+
last_install_at = NOW(),
|
|
98
|
+
activated_at = COALESCE(activated_at, NOW()),
|
|
99
|
+
updated_at = NOW()
|
|
100
|
+
WHERE id = buyer.id;
|
|
101
|
+
|
|
102
|
+
RETURN json_build_object(
|
|
103
|
+
'valid', true,
|
|
104
|
+
'name', buyer.name,
|
|
105
|
+
'install_count', buyer.install_count + 1
|
|
106
|
+
);
|
|
107
|
+
END;
|
|
108
|
+
$$;
|
|
109
|
+
|
|
110
|
+
-- Grant execute to anon role (used by installer CLI via public anon key)
|
|
111
|
+
GRANT EXECUTE ON FUNCTION validate_buyer_email TO anon;
|
|
112
|
+
|
|
113
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
114
|
+
-- UPSERT FUNCTION: sync_buyer_from_sheet
|
|
115
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
116
|
+
-- Called by the sync mechanism (n8n or Google Apps Script)
|
|
117
|
+
-- Upserts a row using email as the unique key
|
|
118
|
+
-- Preserves install tracking data on update
|
|
119
|
+
|
|
120
|
+
CREATE OR REPLACE FUNCTION sync_buyer_from_sheet(
|
|
121
|
+
p_name TEXT,
|
|
122
|
+
p_email TEXT,
|
|
123
|
+
p_phone_ddi TEXT DEFAULT NULL,
|
|
124
|
+
p_phone_ddd TEXT DEFAULT NULL,
|
|
125
|
+
p_phone_number TEXT DEFAULT NULL,
|
|
126
|
+
p_phone_full TEXT DEFAULT NULL
|
|
127
|
+
)
|
|
128
|
+
RETURNS JSON
|
|
129
|
+
LANGUAGE plpgsql
|
|
130
|
+
SECURITY DEFINER
|
|
131
|
+
AS $$
|
|
132
|
+
DECLARE
|
|
133
|
+
result RECORD;
|
|
134
|
+
BEGIN
|
|
135
|
+
INSERT INTO moneyclub_buyers (name, email, phone_ddi, phone_ddd, phone_number, phone_full)
|
|
136
|
+
VALUES (p_name, LOWER(TRIM(p_email)), p_phone_ddi, p_phone_ddd, p_phone_number, p_phone_full)
|
|
137
|
+
ON CONFLICT (email) DO UPDATE SET
|
|
138
|
+
name = EXCLUDED.name,
|
|
139
|
+
phone_ddi = COALESCE(EXCLUDED.phone_ddi, moneyclub_buyers.phone_ddi),
|
|
140
|
+
phone_ddd = COALESCE(EXCLUDED.phone_ddd, moneyclub_buyers.phone_ddd),
|
|
141
|
+
phone_number = COALESCE(EXCLUDED.phone_number, moneyclub_buyers.phone_number),
|
|
142
|
+
phone_full = COALESCE(EXCLUDED.phone_full, moneyclub_buyers.phone_full),
|
|
143
|
+
updated_at = NOW()
|
|
144
|
+
RETURNING id, email, name INTO result;
|
|
145
|
+
|
|
146
|
+
RETURN json_build_object(
|
|
147
|
+
'success', true,
|
|
148
|
+
'id', result.id,
|
|
149
|
+
'email', result.email,
|
|
150
|
+
'name', result.name
|
|
151
|
+
);
|
|
152
|
+
END;
|
|
153
|
+
$$;
|
|
154
|
+
|
|
155
|
+
-- Only service_role can call sync (not anon)
|
|
156
|
+
-- IMPORTANT: PostgreSQL grants EXECUTE to PUBLIC by default on functions.
|
|
157
|
+
-- We must explicitly REVOKE from public/anon to prevent unauthorized inserts.
|
|
158
|
+
REVOKE EXECUTE ON FUNCTION sync_buyer_from_sheet FROM PUBLIC;
|
|
159
|
+
REVOKE EXECUTE ON FUNCTION sync_buyer_from_sheet FROM anon;
|
|
160
|
+
GRANT EXECUTE ON FUNCTION sync_buyer_from_sheet TO service_role;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
-- Migration: 002_premium_token
|
|
2
|
+
-- Description: Add premium_token delivery to email validation
|
|
3
|
+
-- Date: 2026-02-20
|
|
4
|
+
-- Product: Mega Brain - MoneyClub Edition
|
|
5
|
+
--
|
|
6
|
+
-- PURPOSE:
|
|
7
|
+
-- Closes the "premium_token gap": validate_buyer_email() previously returned
|
|
8
|
+
-- only {valid, name, install_count}. After this migration, validated buyers
|
|
9
|
+
-- also receive a premium_token used to clone the mega-brain-premium private repo.
|
|
10
|
+
--
|
|
11
|
+
-- ARCHITECTURE:
|
|
12
|
+
-- system_config table stores the shared read-only GitHub PAT.
|
|
13
|
+
-- validate_buyer_email() reads it and returns it ONLY to validated buyers.
|
|
14
|
+
-- The token never leaves the server unless the buyer is active and validated.
|
|
15
|
+
--
|
|
16
|
+
-- SECURITY:
|
|
17
|
+
-- - system_config has RLS enabled, no anon/public access
|
|
18
|
+
-- - Only service_role can read/write system_config directly
|
|
19
|
+
-- - The token is exposed only through the SECURITY DEFINER function
|
|
20
|
+
-- - The GitHub PAT should have minimal scope: contents:read on mega-brain-premium only
|
|
21
|
+
|
|
22
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
23
|
+
-- TABLE: system_config
|
|
24
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
25
|
+
-- Key-value store for system-level configuration.
|
|
26
|
+
-- Used by RPC functions to retrieve operational secrets.
|
|
27
|
+
|
|
28
|
+
CREATE TABLE IF NOT EXISTS system_config (
|
|
29
|
+
key TEXT PRIMARY KEY,
|
|
30
|
+
value TEXT NOT NULL,
|
|
31
|
+
description TEXT,
|
|
32
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
33
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- RLS: no public/anon access
|
|
37
|
+
ALTER TABLE system_config ENABLE ROW LEVEL SECURITY;
|
|
38
|
+
|
|
39
|
+
CREATE POLICY "service_role_full_access" ON system_config
|
|
40
|
+
FOR ALL
|
|
41
|
+
TO service_role
|
|
42
|
+
USING (true)
|
|
43
|
+
WITH CHECK (true);
|
|
44
|
+
|
|
45
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
46
|
+
-- UPDATED RPC FUNCTION: validate_buyer_email
|
|
47
|
+
-- ═══════════════════════════════════════════════════════════════
|
|
48
|
+
-- Now returns premium_token from system_config on successful validation.
|
|
49
|
+
-- Token is only returned when the buyer is active and email matches.
|
|
50
|
+
|
|
51
|
+
CREATE OR REPLACE FUNCTION validate_buyer_email(buyer_email TEXT)
|
|
52
|
+
RETURNS JSON
|
|
53
|
+
LANGUAGE plpgsql
|
|
54
|
+
SECURITY DEFINER
|
|
55
|
+
AS $$
|
|
56
|
+
DECLARE
|
|
57
|
+
buyer RECORD;
|
|
58
|
+
token TEXT;
|
|
59
|
+
BEGIN
|
|
60
|
+
-- Validate buyer
|
|
61
|
+
SELECT id, email, name, status, install_count
|
|
62
|
+
INTO buyer
|
|
63
|
+
FROM moneyclub_buyers
|
|
64
|
+
WHERE LOWER(email) = LOWER(buyer_email)
|
|
65
|
+
AND status = 'active';
|
|
66
|
+
|
|
67
|
+
IF buyer IS NULL THEN
|
|
68
|
+
RETURN json_build_object(
|
|
69
|
+
'valid', false,
|
|
70
|
+
'reason', 'email_not_found'
|
|
71
|
+
);
|
|
72
|
+
END IF;
|
|
73
|
+
|
|
74
|
+
-- Update install tracking
|
|
75
|
+
UPDATE moneyclub_buyers
|
|
76
|
+
SET install_count = install_count + 1,
|
|
77
|
+
last_install_at = NOW(),
|
|
78
|
+
activated_at = COALESCE(activated_at, NOW()),
|
|
79
|
+
updated_at = NOW()
|
|
80
|
+
WHERE id = buyer.id;
|
|
81
|
+
|
|
82
|
+
-- Fetch premium token from config
|
|
83
|
+
SELECT value INTO token
|
|
84
|
+
FROM system_config
|
|
85
|
+
WHERE key = 'premium_repo_token';
|
|
86
|
+
|
|
87
|
+
RETURN json_build_object(
|
|
88
|
+
'valid', true,
|
|
89
|
+
'name', buyer.name,
|
|
90
|
+
'install_count', buyer.install_count + 1,
|
|
91
|
+
'premium_token', token
|
|
92
|
+
);
|
|
93
|
+
END;
|
|
94
|
+
$$;
|
|
95
|
+
|
|
96
|
+
-- Ensure anon can still call the function
|
|
97
|
+
GRANT EXECUTE ON FUNCTION validate_buyer_email TO anon;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Apply SQL migration to Supabase via REST API (service_role key required)
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* SUPABASE_SERVICE_KEY=eyJ... node apply-migration.mjs 002_premium_token.sql
|
|
7
|
+
* SUPABASE_SERVICE_KEY=eyJ... PREMIUM_REPO_TOKEN=ghp_xxx node apply-migration.mjs 002_premium_token.sql --seed-token
|
|
8
|
+
*
|
|
9
|
+
* The service_role key is in: Supabase Dashboard → Settings → API → service_role (secret)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync } from 'fs';
|
|
13
|
+
import { resolve, dirname } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
|
|
18
|
+
const SUPABASE_URL = 'https://lgbzktgbhowxiwppycbi.supabase.co';
|
|
19
|
+
const SERVICE_KEY = process.env.SUPABASE_SERVICE_KEY;
|
|
20
|
+
const PREMIUM_TOKEN = process.env.PREMIUM_REPO_TOKEN;
|
|
21
|
+
|
|
22
|
+
if (SERVICE_KEY === undefined || SERVICE_KEY === '') {
|
|
23
|
+
console.error('ERROR: SUPABASE_SERVICE_KEY env var required.');
|
|
24
|
+
console.error('Get it from: Supabase Dashboard → Settings → API → service_role (secret)');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const args = process.argv.slice(2);
|
|
29
|
+
const migrationFile = args.find(a => a.endsWith('.sql'));
|
|
30
|
+
const seedToken = args.includes('--seed-token');
|
|
31
|
+
|
|
32
|
+
if (migrationFile === undefined) {
|
|
33
|
+
console.error('Usage: SUPABASE_SERVICE_KEY=... node apply-migration.mjs <file.sql> [--seed-token]');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function runSQL(sql, label) {
|
|
38
|
+
// Use the pg REST endpoint with service_role for DDL
|
|
39
|
+
// Supabase doesn't have a raw SQL endpoint via REST, so we use the
|
|
40
|
+
// PostgREST RPC approach: create a temporary function wrapper
|
|
41
|
+
// Actually, the proper way is using the Supabase Management API or pg directly.
|
|
42
|
+
// For simplicity, we split the SQL into individual statements and use the
|
|
43
|
+
// service_role key with the PostgREST RPC endpoint.
|
|
44
|
+
|
|
45
|
+
// Alternative: use the Supabase SQL editor API
|
|
46
|
+
const response = await fetch(`${SUPABASE_URL}/rest/v1/rpc/`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
'apikey': SERVICE_KEY,
|
|
50
|
+
'Authorization': `Bearer ${SERVICE_KEY}`,
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({ query: sql }),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (response.ok === false) {
|
|
57
|
+
const text = await response.text();
|
|
58
|
+
throw new Error(`${label}: ${response.status} — ${text}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return response.json();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function main() {
|
|
65
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
66
|
+
console.log('║ Mega Brain — Migration Runner ║');
|
|
67
|
+
console.log('╚══════════════════════════════════════════════════════════════╝');
|
|
68
|
+
console.log('');
|
|
69
|
+
|
|
70
|
+
const sqlPath = resolve(__dirname, migrationFile);
|
|
71
|
+
const sql = readFileSync(sqlPath, 'utf-8');
|
|
72
|
+
console.log(` Migration: ${migrationFile}`);
|
|
73
|
+
console.log(` SQL size: ${sql.length} bytes`);
|
|
74
|
+
console.log('');
|
|
75
|
+
|
|
76
|
+
// The Supabase REST API doesn't support raw DDL via PostgREST.
|
|
77
|
+
// The proper way to apply migrations is:
|
|
78
|
+
// 1. Supabase Dashboard → SQL Editor → paste and run
|
|
79
|
+
// 2. supabase db push (Supabase CLI)
|
|
80
|
+
// 3. Direct psql connection
|
|
81
|
+
//
|
|
82
|
+
// This script will attempt the Management API first, then fall back to instructions.
|
|
83
|
+
|
|
84
|
+
console.log(' NOTE: Supabase REST API does not support raw DDL via PostgREST.');
|
|
85
|
+
console.log('');
|
|
86
|
+
console.log(' To apply this migration, use ONE of these methods:');
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(' [1] Supabase Dashboard → SQL Editor:');
|
|
89
|
+
console.log(` Open: https://supabase.com/dashboard/project/lgbzktgbhowxiwppycbi/sql`);
|
|
90
|
+
console.log(` Paste the contents of: ${migrationFile}`);
|
|
91
|
+
console.log(' Click "Run"');
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log(' [2] Supabase CLI:');
|
|
94
|
+
console.log(' npx supabase login');
|
|
95
|
+
console.log(' npx supabase link --project-ref lgbzktgbhowxiwppycbi');
|
|
96
|
+
console.log(` npx supabase db push`);
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log(' [3] Direct psql (if you have the connection string):');
|
|
99
|
+
console.log(` psql "postgresql://..." -f ${migrationFile}`);
|
|
100
|
+
console.log('');
|
|
101
|
+
|
|
102
|
+
if (seedToken) {
|
|
103
|
+
if (PREMIUM_TOKEN === undefined || PREMIUM_TOKEN === '') {
|
|
104
|
+
console.error(' ERROR: --seed-token requires PREMIUM_REPO_TOKEN env var.');
|
|
105
|
+
console.error(' Create a fine-grained PAT at: https://github.com/settings/personal-access-tokens/new');
|
|
106
|
+
console.error(' Scope: mega-brain-premium repo, contents:read only');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(' After applying the migration, run this INSERT in the SQL Editor:');
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(` INSERT INTO system_config (key, value, description)`);
|
|
113
|
+
console.log(` VALUES (`);
|
|
114
|
+
console.log(` 'premium_repo_token',`);
|
|
115
|
+
console.log(` '${PREMIUM_TOKEN}',`);
|
|
116
|
+
console.log(` 'GitHub fine-grained PAT for mega-brain-premium (contents:read)'`);
|
|
117
|
+
console.log(` )`);
|
|
118
|
+
console.log(` ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();`);
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(' Done. Migration file ready at:');
|
|
123
|
+
console.log(` ${sqlPath}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
main().catch(err => {
|
|
127
|
+
console.error('Fatal:', err.message);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
});
|