Impulse AI Docs
Intern dokumentasjon
skipLink.label

Databasearkitektur

Fullstendig dokumentasjon av databasearkitekturen til Impulse AI. Bygget pa Supabase (PostgreSQL) med pgvector for semantisk sok, Row Level Security for tilgangskontroll, og SQL-baserte migrasjoner.

Impulse AI sin datamodell er sentrert rundt impulser — transformasjonstriggende tanker og folelser som klassifiseres som enten contraction (sammentrekning) eller expansion (utvidelse).

profiles (brukerprofil + abonnement)
impulses (kjernetransformasjon, contraction/expansion)
├── sessions (5-stegs prosessering)
├── notes (refleksjoner og takknemlighet)
└── check_ins (sjekk-inn med AI-vurdering)
areas (livsomrader: relasjoner, karriere, helse, ...)
layers (transformasjonslag: fysisk, emosjonell, mental, spirituell)
analytics_insights (AI-genererte monstre og fremgang)

Tabelloversikt

heading.anchorLabel

Primaertabeller

heading.anchorLabel
TabellBeskrivelseNøkkelkolonner
profilesBrukerprofil med abonnementsinformasjonid, email, subscription_tier, subscription_status
impulsesKjernedata — transformasjonstriggerid, user_id, content, classification, processual_status
sessions5-stegs transformasjonssesjonid, impulse_id, classification, status, current_step
notesBrukernotater (refleksjon, takknemlighet)id, user_id, content, note_type, impulse_id
check_insSjekk-inn med AI-vurderingid, user_id, content, classification, ai_assessment
areasLivsomrader (system-definerte)id, name, is_system
layersTransformasjonslag (4 nivaer)id, name, sort_order

Stottetabeller

heading.anchorLabel
TabellBeskrivelse
analytics_insightsAI-genererte monstre (pattern, progress, guidance, synchronicity, shift)
analytics_dashboard_cacheCachet analytikk (1 times TTL)
ai_usageSporing av AI-tokenforbruk per bruker
ai_rate_limitsManedlige AI-bruksgrenser per tier
subscription_configKonfigurerer kvoter per abonnementstier
iap_subscriptionsIn-App Purchase abonnementer (iOS/Android)
iap_transactionsTransaksjonshistorikk
iap_webhook_eventsWebhook-logg fra App Store / Google Play

Impulsmodellen

heading.anchorLabel

Impulser er hjertet i applikasjonen. Hver impuls er binaert klassifisert som enten contraction eller expansion.

CREATE TYPE impulse_classification AS ENUM ('contraction', 'expansion');
CREATE TABLE impulses (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid NOT NULL,
content text NOT NULL,
classification impulse_classification NOT NULL, -- Alltid satt, aldri NULL
processual_status processual_status DEFAULT 'captured',
ai_analysis jsonb, -- AI-anriket innhold
embedding vector(512), -- Voyage AI semantisk vektor
-- ... timestamps, areas, layers
);

Klassifisering

heading.anchorLabel
  • Contraction: Begrensende, fryktbaserte impulser. Prosesseres gjennom Clearing-sesjoner.
  • Expansion: Vekstorienterte, apnende impulser. Prosesseres gjennom Realization-sesjoner.

Prosessuell status (Kanban)

heading.anchorLabel

Impulser folger en enkel kanban-flyt:

StatusBeskrivelse
capturedFanget, ikke prosessert enna
transformingUnder aktiv prosessering (sesjon pagar)
transformedFerdig prosessert

AI-analyse (JSONB)

heading.anchorLabel

Etter fangst berikes impulser asynkront med AI-analyse:

{
"contentValidity": "valid", // valid | low_confidence | gibberish
"validityConfidence": 0.95,
"title": "Frykt for a ikke vaere nok",
"summary": "Du opplever en frykt for at...",
"areas": [
{ "id": "area-uuid", "name": "relationships", "relevanceScore": 0.92 }
],
"layers": {
"primary": {
"layer": "emotional",
"confidence": 0.88,
"reasoning": "Frykt oppleves primaert som emosjonell respons",
"perspective": "Hjertet ditt vet sannheten du laerer"
},
"secondary": { /* valgfri */ }
},
"processedAt": "2026-02-14T10:30:00.000Z"
}

Sesjonsmodellen

heading.anchorLabel

Sesjoner folger The Impulse AI Way — en 5-stegs prosess som er identisk i struktur for bade contraction og expansion, men med ulike AI-prompts per steg.

CREATE TYPE session_status AS ENUM ('created', 'active', 'completed', 'abandoned');
CREATE TYPE session_type AS ENUM ('contraction', 'expansion');
CREATE TABLE sessions (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid NOT NULL,
impulse_id uuid NOT NULL REFERENCES impulses(id),
classification session_type NOT NULL,
status session_status DEFAULT 'created',
current_step integer CHECK (current_step >= 1 AND current_step <= 5),
-- AI-generert veiledning per steg
step_1_guidance text, -- FEEL (Kjenn i kroppen)
step_1_ai_status ai_workload_status DEFAULT 'pending',
step_2_guidance text, -- OWN (Erkjenn energi-investeringen)
step_3_guidance text, -- SHIFT (Tilstand definerer virkelighet)
step_4_guidance text, -- ENVISION (Se for deg ny tilstand)
step_5_guidance text, -- RELEASE (Loskoble og affirmer)
-- Oppsummering
summary_document jsonb, -- AI-generert oppsummering
user_reflection text, -- Brukerens refleksjon
reflection_conclusion text, -- AI-generert konklusjon
-- Embedding for semantisk sok
embedding vector(512),
embedding_model text DEFAULT 'voyage-3-lite',
-- Kostnadssporing
total_input_tokens integer DEFAULT 0,
total_output_tokens integer DEFAULT 0,
total_cost numeric(10,6) DEFAULT 0
);
StegEngelskNorskFormaal
1FEELKjenn i kroppenSomatisk bevissthet
2OWNErkjenn energi-investeringenErkjennelse av investering
3SHIFTTilstand definerer virkelighetTilstand skaper virkelighet
4ENVISIONSe for deg ny tilstandVisualisering og forankring
5RELEASELoskoble og affirmerSlipp og bekreft

Summary Document (JSONB)

heading.anchorLabel

Etter fullfort sesjon genererer AI en oppsummering:

{
"title": "Fra frykt til frihet",
"summary": "I denne sesjonen gikk du fra sammentrekning til apning...",
"startingPoint": "En dyp frykt for fiasko i karrieren",
"newUnderstanding": "Jeg innsa at min verdi ikke bestemmes av ytre suksess",
"breakthroughs": [
"Frykt er ikke sannhet, bare en gammel beskyttelsesmekanisme",
"Jeg har valg i hvordan jeg responderer pa usikkerhet"
],
"nextSteps": [
"Legg merke til nar frykten oppstar og pust inn i den",
"Skriv dagbok om oyeblikk der du folte deg ubetinget akseptert"
],
"process": [
{
"stepNumber": 1,
"stepTitle": "Kjenn (Kjenn i kroppen)",
"keyInsight": "Kjente frykt i brystet og halsen",
"userInputs": ["Stramhet i brystet, restriksjon i halsen"]
}
],
"reflection": "Denne sesjonen markerte et vendepunkt...",
"generatedAt": "2026-02-14T14:45:00.000Z"
}

Sjekk-inn lar brukere logge hva de gjor akkurat na, med AI-vurdering basert pa BE->DO->RECEIVE-filosofien.

CREATE TABLE check_ins (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid NOT NULL,
content text NOT NULL CHECK (char_length(content) >= 1 AND char_length(content) <= 500),
classification text CHECK (classification IN ('contraction', 'expansion', 'neutral')),
ai_assessment jsonb,
ai_assessment_status text DEFAULT 'idle',
embedding vector(512),
-- ...
);

Sjekk-inn kan konverteres til impulser via source_check_in_id-koblingen pa impulses-tabellen.

Omrader og lag

heading.anchorLabel

Areas (livsomrader)

heading.anchorLabel

Dynamiske livsdomener som AI tilordner impulser til:

CREATE TABLE areas (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
name text NOT NULL UNIQUE,
display_name text,
is_system boolean DEFAULT false,
sort_order integer
);

Eksempler: relasjoner, karriere, helse, spiritualitet, kreativitet, okonomi.

Layers (transformasjonslag)

heading.anchorLabel

Fire hierarkiske dimensjoner av opplevelse:

sort_orderLagBeskrivelse
1PhysicalKroppslige opplevelser og sensasjoner
2EmotionalFolelser og emosjonelle reaksjoner
3MentalTankemonster og overbevisninger
4SpiritualDypere mening og forbindelse

Impulser tilordnes primaeert og sekundaert lag med AI confidence score (0.00-1.00).

CREATE TABLE notes (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid NOT NULL,
content text NOT NULL,
note_type note_type DEFAULT 'reflection', -- gratitude | reflection
impulse_id uuid REFERENCES impulses(id), -- valgfri kobling
session_id uuid, -- valgfri sesjonskobling
session_step smallint CHECK (session_step >= 1 AND session_step <= 5),
archived_at timestamptz -- soft delete
);

Notater kan vaere fritstaende, koblet til en impuls, eller koblet til et spesifikt steg i en sesjon.

Brukerprofiler og abonnement

heading.anchorLabel
CREATE TABLE profiles (
id uuid PRIMARY KEY, -- refererer til auth.users.id
email text NOT NULL,
display_name text,
subscription_tier text DEFAULT 'trial', -- trial | foundation | mastery | partner
subscription_status text DEFAULT 'inactive', -- active | inactive | cancelled | past_due
trial_started_at timestamptz,
trial_ends_at timestamptz,
trial_converted boolean DEFAULT false,
preferred_language text, -- en | no
-- ...
);

Abonnementstier

heading.anchorLabel
TierBeskrivelseAI-tilgang
trial7-dagers gratis provperiodeFull tilgang
foundationFoundation-abonnement ($6/mnd)Full tilgang, 30 sesjoner/mnd
masteryMastery-abonnement ($12/mnd)Full tilgang, ubegrenset
partnerGratis for samarbeidspartnereSamme som foundation

Kvoter konfigureres via subscription_config-tabellen og sjekkes gjennom check_impulse_quota()-funksjonen.

Semantisk sok (pgvector)

heading.anchorLabel

Impulser, sesjoner og sjekk-inn har 512-dimensjonale embedding-vektorer generert av Voyage AI (voyage-3-lite).

Likhetsfunksjoner

heading.anchorLabel

Databasen har flere spesialiserte PostgreSQL-funksjoner for semantisk sok:

FunksjonBeskrivelse
find_similar_impulses()Finn impulser lignende en embedding-vektor
find_similar_to_impulse()Finn impulser lignende en gitt impuls (etter ID)
find_similar_sessions()Finn sesjoner lignende en embedding-vektor
find_sessions_similar_to_impulse()Finn sesjoner lignende en impuls
find_similar_check_ins()Finn sjekk-inn lignende en embedding-vektor

Alle funksjoner bruker cosine similarity (1 - (a <=> b)) med konfigurerbar terskel (standard 0.7) og maks antall resultater.

JSONB-konvensjoner

heading.anchorLabel

Hvorfor JSONB-innhold er “opaque”

heading.anchorLabel

JSONB-innhold fra AI-workloads endrer seg ofte nar prompts forbedres. Definer aldri JSONB-innhold i Fastify-skjemaer:

// FEIL -- vil brekke nar AI endrer output
ai_analysis: { type: 'object', properties: { sessionCTA: { ... } } }
// RIKTIG -- behandle som ugjennomsiktig
ai_analysis: { type: ['object', 'null'], additionalProperties: true }

JSONB-felter i databasen

heading.anchorLabel
TabellKolonneInnhold
impulsesai_analysisAI-klassifisering, tittel, sammendrag, omrader, lag
sessionssummary_documentOppsummering med gjennombrudd, neste steg, prosess
check_insai_assessmentBE->DO->RECEIVE-vurdering og coach-forslag
analytics_insightsdata_pointsStottende data for innsikter
analytics_dashboard_cachesummary, timeline, themesCachet analytikk

Migrasjonsarbeidsflyt

heading.anchorLabel

Migrasjoner forvaltes gjennom Supabase CLI:

Terminal window
# 1. Opprett ny migrasjon
pnpm db:migrate:new navn_pa_migrasjon
# 2. Rediger SQL-filen
# packages/database/supabase/migrations/[timestamp]_navn_pa_migrasjon.sql
# 3. Test lokalt
pnpm db:reset
# 4. Generer TypeScript-typer
pnpm db:types
# 5. Verifiser typer
# packages/database/types/database.ts

Supabase-spesifikasjoner

heading.anchorLabel

Aktiverte extensions

heading.anchorLabel
ExtensionFormaal
vectorpgvector for embedding-sok
uuid-osspUUID-generering
pgcryptoKryptografiske funksjoner
pg_graphqlGraphQL-stotte
pg_netHTTP-kall fra databasen
supabase_vaultSikker hemmelighetslagring
EnumVerdierBrukt av
impulse_classificationcontraction, expansionimpulses.classification
processual_statuscaptured, transforming, transformedimpulses.processual_status
session_statuscreated, active, completed, abandonedsessions.status
session_typecontraction, expansionsessions.classification
note_typegratitude, reflectionnotes.note_type
ai_workload_statusidle, pending, processing, complete, failedFlere tabeller
content_validityvalid, low_confidence, gibberishimpulses.content_validity

Database-funksjoner

heading.anchorLabel
FunksjonBeskrivelse
create_user_profile()Trigger: Oppretter profil nar ny auth-bruker opprettes (3-dagers trial)
check_impulse_quota()Sjekker om bruker har gjenvaeerende kvoter for impulsfangst og sjekk-inn
check_impulse_deletable()Returnerer true hvis impuls ikke har relaterte sesjoner
delete_impulse_safe()Sikker sletting med eierskap- og relasjonssjekk
expire_trials()Planlagt funksjon for a markere utlopte trials