platform-base — Fejlesztési módszer

platform-base — Fejlesztési módszer

Document = Code · Declarative Logic · Four Engines

39 repo · 800+ pipeline · 90+ adapter

entity-forgepipeline-forgeGoBIPostgreSQLai-chatRAGlookin
Alapelvek

Három alapillér

Document = Code

Spec = Futtatható

  • Az .md fájl egyszerre emberi spec és motor-input
  • Nincs külön dokumentáció — a spec önmagyarázó
  • Diff-elhető, review-olható, version-controlled
  • Komment a mirértet magyarázza, nem a mit

Artefaktok: entities/EN-*.md · lov/*.md · pipelines/*.md

Logic in Pipelines

Üzleti logika ≠ Go kód

  • Többlépéses folyamatok → pipelines/*.md
  • Go/Python = motor (engine), nem orchestrátor
  • Változás = pipeline szerkesztés, nincs recompile
  • Egységes retry, audit, suspend/resume minden folyamatra

Motor: pipeline-forge bin/pf

Data > Hardcode

Konfiguráció = adat

  • Model neveket, tenant értékeket, label-eket soha ne hardcode-olj
  • DB registry / config YAML az igazság forrása
  • Capability-based filtering, nem name-based
  • DB generálja az időbélyegeket, nem a backend

Identitás értékek: env var / config — soha default

Mielőtt cmd/<folyamat>/main.go-t írsz: “Lehetne ez pipeline fájl?”

Ha egynél több lépés van → igen, pipeline fájl. Ha LLM-hívást kell orchestrálni → az ai-chat engine.AIClient-en át, soha saját provider HTTP.

Ötödik motor tervezése (saját workflow runner, LLM router, parallel pipeline framework)?

Állj meg! A platform már rendelkezik a négy szükséges motorral. Adj hozzá adaptert vagy bővítsd a spec formátumot.

Motor összehasonlítás

entity-forge vs pipeline-forge — mikor melyiket?

entity-forge — mikor?

  • Új entitás, LOV, form, BI nézet tervezésekor
  • DDL + Go CRUD + HTMX template egyszerre kell
  • A spec (EN-*.md) generálja az összeset

pipeline-forge — mikor?

  • Többlépéses folyamat (ETL, RAG, email, jóváhagyás)
  • Változás = pipeline szerkesztés, nincs recompile
  • Suspend/resume, retry, audit automatikusan
Kód generálás

entity spec → kész alkalmazás — az egész folyamat

Bemenet: spec fájl

  • 1 db EN-*.md — tábla, mezők, CRUD, form, AI kontextus
  • Emberi olvasásra szánt, ez a forrás az igazsághoz
  • LOV spec: szótár táblák, enum értékek

Motor: entity-forge + pipeline-forge

  • Parancs: SKIP_DIRTY_CHECK=1 bash scripts/build.sh
  • entity-forge: SQL, Go, HTML, JSON egyszerre
  • pipeline-forge: pipeline lépések végrehajtása (pfbridge)

Kimenet: kész alkalmazás

  • PostgreSQL: DDL migrációk + stored functions
  • Go alkalmazás: handler, template, datagrid
  • Generált fájlokat soha ne szerkeszd kézzel!
Tudásbázis

RAG — tartalom és kontextus együtt

Tartalom — vektor DB

  • A chunkok beágyazása (pgvector, HNSW)
  • Szemantikus keresés: mi szól a kérdésről
  • Az alkatrészek

Kontextus — él-gráf

  • Kapcsolatok a dokumentumok között: hivatkozás, szerző, kulcsszó
  • A találatok szomszédai: hogyan függ össze
  • Az összeszerelés — tartalom nélkül üres, kontextus nélkül szétszórt

Rangsor → prompt → LLM

  • Reranker: a jelöltekből a legjobb N (cross-encoder)
  • Teljes prompt: kérdés + tartalom + kontextus
  • LLM-válasz, a forrásokra hivatkozva
AI chat

AI chat futás — kérdéstől a válaszig

Chat felület — belépési pont

  • SSO autentikáció — multi-corporate
  • WebSocket: valós idejű chat felület
  • Persona-alapú személyre szabás

Tudáslekérdezés

  • MCP tudásszerver: RAG szemantikus keresés a RAG DB-ből
  • NL → SQL: természetes nyelvű DWH lekérdezés
  • Kontextus összeállítás az LLM számára

LLM — válasz generálás

  • Ollama: helyi GPU szerver — adatvédelem
  • Gemini / Claude: felhő API — teljesítmény
  • ai-chat diszpécser: modell + tenant alapján választ
entity-forge

entity-forge — Mi mit generál?

Input: Entity spec

entities/EN-018_dokumentum_tipus.md

  • HEADER — metaadat (schema, SCD2, RLS…)
  • COLUMNS — mezők, típusok, LOV hivatkozások
  • RELATIONSHIPS — FK és back-referenciák
  • CRUD — generálandó műveletek listája
  • FORMS — create / edit / view variánsok
  • AI_CONTEXT — AI számára teljes kontextus

Generálás parancs

SKIP_DIRTY_CHECK=1 \
  bash scripts/build.sh

# Eredmeny:
# OK  EN-018_dokumentum_tipus.md
#     -> 9 file(s)

Generált fájlokat soha ne szerkeszd!

Generált fájl Tartalom
database/generated/EN-018_*.sql DDL + CRUD stored functions: list, get, insert, update, expire
internal/catalog/dokumentum_tipus.json Datagrid column catalog — oszlopok, típusok, rendezés
ui/pages/dokumentum_tipus_list.html Lista oldal HTMX template
ui/partials/*_rows.html Datagrid sorok HTMX fragment
ui/partials/*_form_create.html Create/edit form HTMX fragment
internal/handlers/*_gen.go Go handler — list, form, save, expire
bi/queries/app/dokumentum_tipus.md GoBI BI lekérdezés fájl (mks_sql_parser)
pipelines/WF-dokumentum_tipus-*.md Workflow scaffold — create / update / expire
resources/entity_{en,hu}.json i18n label kulcsok

Mező változtatás, LOV hozzáadás, form variáns módosítás?

Szerkeszd az entities/EN-*.md spec-et, futtasd újra a build.sh-t. Ne nyúlj a generált fájlokhoz.

entity-forge

Entity spec formátum — Annotált minimális példa

entity: EN-001
name: category
schema: app
table: app.category
type: Torzsadat
sensitivity: Alacsony
# ^ Alacsony -> RLS nem kotelezo
scd2: false
# ^ false -> mutable tabla, nincs temporal lanc
rls: false
business_key: code

COLUMNS

- name: code
  type: text
  required: true
  business_key: true
  labels: { en: "Code", hu: "Kod" }

- name: name
  type: text
  required: true
  list:
    sort: true
  labels: { en: "Name", hu: "Megnevezes" }

- name: description
  type: text
  display:
    list_visible: false
  labels: { en: "Description", hu: "Leiras" }

FORMS

create:
  fields: [code, name, description]
edit:
  inherit: create
view:
  inherit: edit
  readonly_roles: [all]

CRUD

generate: [list, get, insert, update, expire]
list:
  search_fields: [code, name]
  default_sort: { field: name, dir: asc }
  page_sizes: [25, 50]

HEADER kulcsmezők

Mező Hatás
scd2: true Generál valid_period tstzrange, is_current, audit mezőket, btree_gist constraint-et
rls: true Automatikus ENABLE ROW LEVEL SECURITY + policy generálás
sensitivity Alacsony / Közepes / Magas — Közepes felett RLS kötelező
tenant_partitioned Multi-tenant izolálás tábla szinten

Mező típusok

text integer numeric boolean date timestamptz uuid enum (LOV) jsonb text[]

SCD2 + RLS bekapcsolva

sensitivity: Kozepes
# ^ -> RLS kotelezo
scd2: true
# ^ -> valid_period tstzrange,
#   is_current GENERATED ALWAYS AS
#   (upper_inf(valid_period)) STORED,
#   btree_gist EXCLUDE USING gist
rls: true
# ^ -> meta.has_tenant_access policy
entity-forge

Generálás folyamata — Entity spec → Production kód

Spec szerkesztése

  • Mező hozzáadás/módosítás az EN-*.md-ben
  • LOV hivatkozás, sensitivity, scd2 flag
  • Form variáns, CRUD műveletek

Generálás + build

SKIP_DIRTY_CHECK=1 \
  bash scripts/build.sh
  • entitygen parser futása
  • go build ./... az összes generált fájllal

Migration

migrate \
  -path ./migrations \
  -database $DB_URL up
  • Idempotens SQL — újrafuttatható
  • DDL tervet mutasd meg előbb!
pipeline-forge

Pipeline formátum — Valós példa: Napi ETL

Napi ETL

Pipeline

name:     "dwh_daily_etl"
trigger:  "dwh_etl"
schedule: "0 2 * * *"

Adapters

http:
  dwh_url: "${DWH_URL}"
db:
  dsn: "${PG_DSN}"
llm:
  provider:    "${AI_PROVIDER}"
  temperature: 0.1
smtp:
  host:   "${SMTP_HOST}"
  to_ops: "${ETL_OPS_EMAIL}"

Step: trigger_etl — http

config:
  url:    "${config.adapters.http.dwh_url}/scheduler/run"
  method: POST
  body:   "job_key=etl:full"
  output_key: trigger_response
on_error: etl_unreachable

Step: poll_etl_completion — shell

config:
  output_key: etl_final_status
on_error: send_timeout_alert
for i in $(seq 1 180); do
  STATUS=$(psql "${PG_DSN}" -t -A -c \
    "SELECT status FROM meta.etl_log
     WHERE table_name='etl:full'
     ORDER BY start_time DESC LIMIT 1")
  case "$STATUS" in SUCCESS|FAILED|PARTIAL)
    echo "$STATUS"; exit 0;; esac
  sleep 60
done

Step: summarize_run — llm_generate

config:
  provider:      "${config.adapters.llm.provider}"
  system_prompt: "Be concise and factual."
  output_key:    email_body

Step: send_etl_report — smtp

config:
  subject: "[dwh] ETL ${etl_final_status}"
  body_key: email_body

Pipeline fájl sémája

  • # Title — H1 első sorban
  • ## Pipeline YAML blokk: name, trigger, schedule
  • ## Adapters blokk: megosztott kapcsolatok
  • Lépés: ## Step: <id> — <adapter>

on_error routing

  • Névvel hivatkozott lépésre ugrik hibánál
  • Külön etl_unreachable és send_timeout_alert ágak
  • Nincs külön exception handler kód

Interpoláció

  • ${config.adapters.llm.provider} — adapter config
  • ${etl_final_status} — előző lépés output
  • ${PG_DSN} — környezeti változó
pipeline-forge

Adapter könyvtár

Csoport Adapter Mit csinál
DB db_query SELECT stored function-ön át
db_execute INSERT/UPDATE stored function-ön át
postgres Raw SQL (admin use only)
HTTP http Általános HTTP hívás
jira JIRA REST API (issues, transitions)
confluence Confluence REST + page fetch
AI llm_generate LLM szöveg generálás
embed_query Ollama embedding
rerank Cross-encoder reranking
RAG rag_search pgvector HNSW keresés
rag_compact_search Tömörített RAG output
output Pipeline eredmény formázás
Control human_task Emberi jóváhagyás (suspend/resume)
rule_engine SZ-xx üzleti szabály futtatás
log Strukturált GELF log
IO smtp Email küldés
shell Shell script futtatás

Teljes adapter regisztrálása — 6 hely

  1. adapter/<type>/<type>.go — Adapter interface
  2. cmd/pf/main.go — reg.Register(...)
  3. cmd/pf-ui/server.go NewServer() — Register
  4. cmd/pf-ui/server.go builtinStepTypes
  5. cmd/pf-ui/ui/dag.css — .node--<type>
  6. docs/adapters/<group>.md — dokumentáció

Step interpoláció

{{ $payload.tenant }}
# ^ input payload mezo

{{ $node["Step Id"].json.field }}
# ^ elozo step output erteke

${config.adapters.db.dsn}
# ^ adapter konfig referencia

${ETL_OPS_EMAIL}   # env var
${TODAY}           # beepitett valtozo
pipeline-forge

Workflow pipeline-ok — Suspend / Resume emberi jóváhagyással

Step: Manager Approval — human_task

config:
  name:        "Vezető jóváhagyás"
  assignee_id: "{{ $payload.manager_id }}"
  due_hours:   48
# Első futás:
#   INSERT pending sor (SCD2), suspend.
# Resume (jóváhagyás után):
#   lezárt sor olvasása és folytatás.

Go Workflow API

// Inditas
res, err := pipelines.StartWorkflow(
  ctx, tenant, code, "WF-name",
  entityType, entityID, actorID,
  map[string]any{"key": val})
// res.Status == RunSuspended

// Folytas (jovahagyas utan)
res, err = pipelines.ResumeWorkflow(
  ctx, tenant, code, actorID,
  map[string]any{"lang": "hu"})

Pipeline családok

  • FY — üzleti folyamat
  • INT — integráció
  • WF — workflow scaffold (entitygen)
  • RULE — üzleti szabályok

Megfigyelhetőség

  • Minden futás → meta.pipeline_run sor
  • GELF strukturált logging stdout-ra
  • bin/pf --dry-run pipeline.md
  • on_error: named_step fallback routing

Trigger típusok

  • manual — kézi / API indítás
  • cron — ütemezett (cron kifejezés)
  • event — esemény-vezérelt
  • workflow — hosszan futó suspend/resume
GoBI

GoBI — BI lekérdezések és mks_sql_parser dinamikus SQL

Document types

Report

icon: "ph ph-chart-bar"
title:
  en: "Document types"
  hu: "Dokumentumtipusok"

Parameters

- name: status
  type: TEXT
  input: "lov:SELECT code AS value,
    lov.label(name, :current_lang)
    AS label FROM lov.aktiv_statusz
    WHERE active ORDER BY sort_order"
  labels: {en: Status, hu: Statusz}

SQL

SELECT dt.dokumentum_tipus_code,
       dt.tipusnev,
       lov.label(ls.name,
         :current_lang) AS statusz
  FROM app.dokumentum_tipus dt
  LEFT JOIN lov.aktiv_statusz ls
         ON ls.code = dt.aktiv_statusz
        AND ls.active
 WHERE dt.tenant_code = :tenant
--<status
   AND dt.aktiv_statusz = :status
-->
   AND dt.is_current
 ORDER BY dt.tipusnev

COLUMNS

- column: dokumentum_tipus_code
  labels: {en: Code, hu: Kod}
- column: statusz
  labels: {en: Status, hu: Statusz}

mks_sql_parser — Dinamikus SQL szintaxis

SELECT id, name, status
  FROM app.entity
 WHERE is_current              -- mindig bent
--<admin
   AND role = 'admin'          -- ha {"admin":true}
-->
   AND tenant_code = :tenant   -- :param subst.
   AND status = '%status%'     -- %key% subst.
   AND type = $1->>'type'     -- #'type' (sor ha truthy)
Szintaxis Hatás
--<KEY … --> Block: csak ha KEY truthy a JSON-ban
:key Param — sor törlődik ha kulcs hiányzik
%key% Érték — üres string ha kulcs hiányzik
… -- #'key' Line filter — sor csak ha KEY truthy (érték nem helyettesítődik)

Példa: WHERE status = $1->>'status' -- #'status' — sor csak ha status jelen van a JSON-ban

mks_parser JSONB operátorok

-># numeric · ->^ bigint · ->@ timestamp · ->& boolean · ->>> text[] · ->^^ int[] · === array eq

Két futtatási mód: PG extension (SELECT mks_parser($sql, $json)) és Go bi.PreprocNative (CI). Mindkét mód azonos SQL-t kell adjon ugyanarra az inputra.

Adatbázis

JSONB CRUD minta — Minden adat stored function-ön át

SOHA — Inline DML Go/Python kódban

// BAD -- kozvetlen DML
pool.Exec(ctx,
  `INSERT INTO app.entity (name, tenant_code)
   VALUES ($1, $2)`, name, tenant)

# BAD -- kozvetlen SELECT
cur.execute("SELECT * FROM dwh.dim_user
  WHERE user_key = %s", (key,))

MINDIG — Stored function hívás

// GOOD -- Go caller
payload, _ := json.Marshal(map[string]any{
    "tenant": tenant, "id": id})
var raw []byte
pool.QueryRow(ctx,
    "SELECT app.entity_get($1::jsonb)",
    string(payload)).Scan(&raw)

# GOOD -- Python caller
cur.execute(
    "SELECT dwh.user_get_key(%s)", (name,))

JSONB function minta (SQL)

CREATE OR REPLACE FUNCTION app.entity_list(p_data jsonb)
RETURNS jsonb
LANGUAGE sql STABLE SECURITY DEFINER
SET search_path = pg_catalog, app, meta AS $fn$
    SELECT jsonb_build_object(
        'rows',  jsonb_agg(row_to_json(r)),
        'total', COUNT(*) OVER ()
    )
    FROM (
        SELECT col1, col2, col3
          FROM app.entity
         WHERE tenant_code = p_data->>'tenant'
           AND is_current
         ORDER BY col1
         LIMIT  COALESCE((p_data->>'limit')::int, 25)
         OFFSET COALESCE((p_data->>'offset')::int, 0)
    ) r;
$fn$;

Miért JSONB?

  • Mező hozzáadás = csak JSON payload változik
  • Nincs function signature change
  • Nincs Go/Python caller change
  • Nincs pipeline step change

Időbélyegek — DB generálja

-- GOOD: DB clock
INSERT INTO app.entity (name, created_at)
VALUES ($1, now());

-- BAD: backend clock -- soha ne adj
-- time.Now() / datetime.now() parametert!
Adatbázis

SCD2 — Temporal Versioning & Row Level Security

SCD2 táblaszerkezet (generált DDL)

CREATE TABLE app.dokumentum_tipus (
  id          uuid NOT NULL DEFAULT gen_random_uuid(),
  tenant_code text NOT NULL,
  -- business columns:
  dokumentum_tipus_code text NOT NULL,
  tipusnev              text,
  -- SCD2 audit cols (entity-forge generalja):
  valid_period tstzrange NOT NULL
                DEFAULT tstzrange(now(), NULL),
  is_current   boolean GENERATED ALWAYS AS
                (upper_inf(valid_period)) STORED,
  created_at   timestamptz NOT NULL DEFAULT now(),
  updated_at   timestamptz NOT NULL DEFAULT now(),
  PRIMARY KEY (tenant_code, id, valid_period),
  -- Egy tenant_code+id par nem fedhet at
  -- valid_period szerint (btree_gist kell):
  EXCLUDE USING gist (
    tenant_code WITH =, id WITH =, valid_period WITH &&)
);

SCD2 olvasás és mutáció

-- Aktualis rekordok (ket egyenerteeku mod):
WHERE upper_inf(valid_period)  -- pontos
WHERE is_current               -- kényelmes

-- Historikus lekerdezés:
WHERE valid_period @>
  '2026-01-15'::timestamptz

Soha ne adj raw UPDATE-et SCD2 táblákon! Mindig CRUD function-ön át; a leaf partíciókon btree_gist && constraint véd.

RLS Policy (generált)

ALTER TABLE app.dokumentum_tipus
  ENABLE ROW LEVEL SECURITY;

CREATE POLICY p_read
  ON app.dokumentum_tipus FOR SELECT
  USING (meta.has_tenant_access(tenant_code));

CREATE POLICY p_write
  ON app.dokumentum_tipus FOR INSERT
  WITH CHECK (
    meta.can_write_tenant(tenant_code));
SCD2 partíció sensitivity rule
leaf partíciók Alacsony → RLS opcionális ENABLE RLS + policy együtt mindig
btree_gist && constraint Közepes → RLS kötelező App nem re-számolja a tenant filtert
Magas → RLS + auditlog SECURITY DEFINER + search_path
RAG

RAG architektúra — 3 rétegű MCP tudásszerver

RAG collectionök

Collection Tartalom
JIRA ticketek, kommentek
Confluence specifikációk, döntések
Web külső dokumentáció
DWH issue metaadat + worklog

Write: 3-step Audit Loop

  1. Enqueue: INSERT audit sor (pending)
  2. Call: JIRA REST POST (per-user PAT)
  3. Finalize: UPDATE audit sor (HTTP status, key)

Embedding

  • Ollama snowflake-arctic-embed2
  • GPU szerver (Ollama)
  • pgvector HNSW index
  • Reranker: cross-encoder (llama-swap)

Search logic helye

  • Keresési logika: pipelines/*.md
  • MCP szerver = engine, nem search
  • Link rendering a szerverben
  • pf binary: PF_BIN → bin/pf → PATH

DWH hozzáférés

  • Csak dwh.* SECURITY DEFINER function
  • Nincs SELECT a dim_* táblákon
  • LDAP tilos — DWH tükrözi az attribútumokat
  • 'me': $USER env var → DWH
Biztonság

Biztonsági modell — Védelemben mélység (Defense in Depth)

GPG Vault szabályok

  • Commitálva: .env.gpg (titkosított)
  • Gitignore: .env — soha ne commitáld
  • API kulcsok fejlécben, soha URL-ben
  • Log-ban titkot soha — *** masking

Input validation szabályok

  • SQL injection: soha string concat, $1 mindig
  • Path traversal: filepath.Clean() + base ellenőrzés
  • Dynamic identifier: ^[a-zA-Z_][a-zA-Z0-9_.]*$
  • YAML: csak yaml.safe_load() — soha yaml.load()
  • AI SQL: timeout ≤ 5s, sor limit ≤ 1000

SECURITY DEFINER

  • App role: EXECUTE jogosultság
  • Nincs SELECT a dim_* táblákon
  • Function: search_path = pg_catalog, schema
  • AI SQL: default_transaction_read_only=on

Tenant izoláció

  • RLS: meta.has_tenant_access(tenant_code)
  • App soha ne re-számolja a filtert
  • GUC: SET app.tenant_code = $1 session-ben
  • SCD2 btree_gist izoláció

Web biztonság

  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • WebSocket: origin allowlist, soha return true
  • Template: soha template.HTML cast untrusted data
Fejlesztési workflow

Git workflow · Build · Deploy · Cross-project blast radius

Branch naming

feature/* fix/* data/* ai/* docs/*

  • Solo repo: közvetlen push main-re, ellenőrzés után
  • GitLab-kanonikus repo: merge request
  • Issues: [repo-name] prefix a GitHub project-ben
  • Milestone → negyedéves release

Deploy flow

  1. Ellenőrzés — systemctl status (prod szerver)
  2. Build — go build ./... bináris commit
  3. Push — git push main branch
  4. Deploy — deploy script + systemctl restart

Cross-project blast radius

  • Library szerkesztés előtt: olvasd a projects.md Connections-t
  • Nyilvános API változás → build összes consumer előbb
  • mks_parser($sql text, $json text) — soha ne törd
  • go.mod replace direktívák = azonnal propagál
# Pre-commit Go
/usr/local/go/bin/go build ./...
/usr/local/go/bin/go vet ./...
/usr/local/go/bin/go test ./...

# Pre-commit Python
ruff check . && black --check .
python -m pytest

Ne csináld — Platform szabályok

  • ORM tilos — pgx/v5 + pgxpool az új kódba
  • SPA framework tilos — HTMX + vanilla JS
  • Frontend build lépés tilos lookin-ba
  • Migration futtatás terv + jóváhagyás nélkül tilos
  • Tenant értékek hardcode-olása Go/JS kódba tilos
  • Közvetlen DML táblákon tilos — function-ön át