AisOpsFlow v0.1 제품 명세 및 현재 상태

목표: 알림 → 승인 → 실행 → 보고 흐름을 멱등성, 재시도, 감사 로그, 멀티채널 알림과 함께 제공하는 Ops/IT 자동화 플랫폼

아키텍처: Haskell Core + 플러그인 기반 어댑터(채널 + 도구). 워크플로는 YAML 로 정의되며 저장소는 SQLite 를 사용합니다.

구현 메모:

  • 이 문서는 현재 저장소에서 동작하는 기능과 앞으로의 계획을 구분합니다.
  • 어떤 기능이 planned 로 표시되면, 제품 방향에는 포함되지만 현재 이 저장소에 완전히 구현된 상태는 아닙니다.

1) 대상 사용자와 핵심 가치

  • 대상: 일반적인 엔터프라이즈 Ops/IT 팀(SRE/Infra/IT Ops)
  • 구매 가치: 수동 런북 단계 감소, 더 빠른 장애 대응, 누락 감소, 감사 가능성
  • 핵심 약속: 기본적으로 안전한 워크플로 자동화
    • 위험한 작업에 대한 승인 게이트
    • 중복 제거 / 멱등성
    • 타임아웃 / 재시도 / 백오프
    • 감사 추적

2) 배포 모드(동일 코드, 다른 설정)

모드 A: 온프렘(Docker Compose)

  • 단일 테넌트
  • SQLite 로컬 파일
  • 고객이 소유한 자격 증명 사용(예: Kakao 고객사 공급자)

모드 B: SaaS

  • 멀티테넌트(테이블에 tenant_id 포함)
  • 초기에는 SQLite 사용(향후 Postgres 전환을 고려한 스키마)
  • 다음 두 방식을 모두 지원
    • customer providers: 고객이 소유한 메시징 계정
    • managed providers: 운영사가 관리하는 리셀러/매니지드 계정

3) 채널(v0.1)

주요 채널(v0.1): Slack

v0.1 에 포함되는 채널:

  • Email(SMTP)
  • Telegram
  • 공급자 추상화를 통한 Kakao 알림톡
  • Teams direct webhook targets

4) 워크플로 정의(YAML)

4.1 최상위 필드

필수:

  • id: string
  • name: string
  • triggers: Trigger[]
  • steps: Step[]

선택:

  • enabled: bool (기본값 true)

계획되어 있으나 아직 파싱하지 않는 항목:

  • vars: object (전역 템플릿 변수)

4.2 트리거

현재 구현됨:

  • webhook: { type: webhook, path: string, dedupe_key?: string, auth?: WebhookAuth }
  • cron: { type: cron, expr: string }

dedupe_key 는 중복 실행을 막기 위한 템플릿 표현식입니다.

4.3 단계 타입

현재 구현됨:

  • http
  • notify
  • approval (Slack interactive)
  • condition

공통 단계 필드:

  • id: string
  • type: enum
  • timeout_seconds?: number
  • retry?: { max: number, backoff_ms: number }
  • when?: string (템플릿 표현식)

4.4 Notify 대상

Notify 단계는 Kakao 알림톡을 포함한 여러 대상을 지원합니다.

예시 대상 목록:

  • slack.<channel>
  • email:<address>
  • telegram:<chatIdOrAlias>
  • teams:<webhookUrlOrSuffix>
  • kakao: ... (구조화된 대상, §6 참고)

현재 저장소 메모:

  • 일반 워크플로 notify 실행은 Slack/Email/Telegram/Teams direct target 을 라우팅하고, group:<name> / recipient:<id> 디렉터리 참조를 확장하며, 구조화된 Kakao payload 를 정규화합니다.

5) 수신자와 그룹(v0.1)

AisOpsFlow 는 수신자와 그룹을 중앙에서 관리합니다.

현재 저장소 메모:

  • recipient CRUD, group CRUD, group membership 교체/조회 API 구현됨

  • Kakao send-test 는 group:<name>recipient:<id> 를 전화번호로 확장함

  • 일반 workflow notify 단계도 실행 시 디렉터리 참조를 확장함

  • Recipient 최소 필드:

    • name
    • phone?
    • email?
    • slack_id?
    • telegram_id?
    • teams_id? (향후)
  • Group:

    • name
    • members[] (recipient 참조)

6) Kakao 알림톡 공급자 추상화

6.1 왜 추상화가 필요한가

Kakao 알림톡은 보통 서로 다른 API 를 가진 중계사/공급자 를 통해 전송됩니다. AisOpsFlow 는 하나의 공급자 인터페이스를 표준화하고, 각 공급자를 플러그인으로 추가합니다.

6.2 Core 가 관리하는 템플릿 레지스트리

Core 는 전송 전에 필수 변수를 검증하기 위해 테넌트별 템플릿을 저장합니다.

  • provider_id
  • template_id
  • required_vars[]
  • description
  • active

6.3 YAML 대상(계획된 표준 형태)

- kakao:
    mode: alimtalk
    provider: "<provider-id>"
    template_id: "ops_alert_v1"
    to:
      - "01012345678"
      - group:oncall-l1
    vars:
      system: "prod"
      host: "{{body.host}}"
      summary: "{{steps.run.body.summary}}"
    fallback:
      - slack.ops-alerts
      - email:oncall@company.com

규칙:

  • to[] 는 전화번호 또는 group:<group-name> 을 포함할 수 있습니다.
  • Core 가 그룹을 전화번호 목록으로 확장합니다.
  • Core 가 vars 에 템플릿의 모든 required_vars 가 포함되는지 검증합니다.
  • 공급자 실패 시 Core 가 fallback 대상을 자동 전송합니다.

현재 저장소 메모:

  • Kakao template CRUD 와 POST /api/kakao/send-test 검증 구현됨
  • send-testrequired_vars 를 검증하고 group: / recipient: 대상을 확장함
  • Workflow notify 실행은 구조화된 Kakao payload 를 보내고, 공급자 실패 시 runner 측 fallback 자동화가 Slack/Email/Telegram fallback target 을 재시도할 수 있음

6.4 공급자 플러그인 계약(HTTP/JSON)

공급자 플러그인은 다음을 구현해야 합니다.

  • POST /probe
  • POST /kakao/alimtalk/send

요청:

{
  "tenant_id": "t_...",
  "provider_id": "...",
  "template_id": "ops_alert_v1",
  "to": ["01012345678"],
  "vars": {"host": "..."},
  "trace_id": "..."
}

응답:

{
  "ok": true,
  "provider_message_id": "...",
  "result": {"accepted": 1, "failed": 0},
  "error": null
}

현재 저장소 상태:

  • 번들 구현은 단일 mock provider 와 delivery-event simulator 를 사용합니다.
  • 추가 공급자 플러그인은 향후 작업입니다.

7) API 표면(v0.1)

인증(email/password)

  • POST /api/login
  • POST /api/logout

워크플로

  • GET /api/workflows
  • PUT /api/workflows/{id} (YAML 업로드)
  • POST /api/workflows/{id}/enable
  • POST /api/workflows/{id}/disable
  • POST /api/hooks/{workflowId} (webhook endpoint)

실행

  • GET /api/executions?workflow_id=&status=&limit=
  • GET /api/executions/{id}
  • POST /api/executions/{id}/retry

수신자 / 그룹

  • recipients CRUD
  • groups CRUD
  • group membership 관리

Kakao templates

  • templates CRUD
  • POST /api/kakao/send-test

Health

  • GET /healthz

Commercial ops baseline

  • GET /api/ops/managed-providers
  • PUT /api/ops/managed-providers/{providerKind}
  • DELETE /api/ops/managed-providers/{providerKind}
  • GET /api/ops/backup/export
  • POST /api/ops/backup/validate
  • POST /api/ops/backup/import
  • GET /api/ops/runner-denylist
  • PUT /api/ops/runner-denylist/{runnerId}
  • DELETE /api/ops/runner-denylist/{runnerId}

Agent(LLM 계획 + dispatch)

  • POST /api/agent/llm-plan-and-dispatch (자연어 → shell/db plan → policy → dispatch)
  • POST /api/agent/llm-plan
  • POST /api/agent/execute-planned-job
  • GET /api/runner/job-results/{jobId}
  • GET /api/agent/decision-traces

8) 저장소(SQLite schema, v0.1)

모든 테이블은 tenant_id 를 포함합니다. 온프렘은 단일 테넌트를 사용합니다.

현재 저장소 메모:

  • canonical schema 는 Beam 에서 관리
  • SQLite, Postgres, MySQL backend 가 이 저장소에 구현되어 있음

Core 테이블:

  • tenants(id, name, mode, created_at)
  • users(id, tenant_id, email, password_hash, role, created_at)
  • workflows(id, tenant_id, name, yaml, enabled, created_at, updated_at)
  • executions(id, tenant_id, workflow_id, status, dedupe_key, trigger_type, trigger_ref, started_at, ended_at, error_summary)
  • step_runs(id, tenant_id, execution_id, step_id, status, started_at, ended_at, input_redacted, output_redacted, error)

Recipients & groups:

  • recipients(id, tenant_id, name, phone, email, slack_id, telegram_id, created_at)
  • groups(id, tenant_id, name)
  • group_members(group_id, recipient_id)

Kakao templates:

  • kakao_templates(id, tenant_id, provider_id, template_id, required_vars_json, description, active, created_at)

Security & ops:

  • secrets(key, tenant_id, ciphertext, created_at, rotated_at)
  • audit_log(id, tenant_id, actor, action, target, ts, metadata_redacted)

9) 플러그인과 런타임 모델

  • 플러그인은 별도 프로세스/컨테이너로 실행됩니다.
  • Core 는 HTTP 로 플러그인을 호출합니다.

공통 엔드포인트(모든 플러그인):

  • POST /probe

채널 플러그인의 표준 엔드포인트:

  • POST /send

Slack 승인 흐름(v0.1):

  • Core 가 Slack 플러그인으로 interactive button 이 포함된 메시지를 전송
  • Slack 플러그인이 interaction callback 을 수신
  • Slack 플러그인이 Core 호출
    • POST /api/approvals/{executionId}/{stepId}/resolve

10) 온프렘 패키징(Docker Compose)

서비스:

  • aisopsflow-core
  • plugin-slack
  • plugin-email
  • plugin-telegram
  • plugin-kakao-provider-<id> (최소 하나)

볼륨:

  • SQLite DB 파일
  • secrets store
  • 선택적 workflows directory

11) MVP 마일스톤(권장)

  • 이 저장소에 이미 구현됨:
    • webhook workflow, executions, retries, approvals, audit logs
    • cron trigger, condition step, when expression
    • Slack/Email/Telegram 알림 플러그인
    • Teams direct notify 플러그인
    • Kakao template CRUD, mock provider, delivery-event simulator, directory-backed notify expansion, fallback automation
    • SQLite/Postgres/MySQL 을 위한 멀티테넌트 API 와 backend 지원
    • managed provider config API, administrative write rate limit, backup export/validate/import, runner denylist control, Beam tenant slug backfill
    • Core↔︎Runner gRPC dispatch, job result, heartbeat, log, signed dispatch/result validation, enrollment, token rotation, durable outbox replay, inventory, Core-signed CSR renewal, operator-managed fallback renewal hook
  • 남은 로드맵 항목:
    • 더 엄격한 컴플라이언스가 필요할 경우 certificate fingerprint 또는 CRL/OCSP 스타일 폐기
    • merge 스타일 import 를 넘어서는 destructive replace/rollback restore 모드
    • Teams 도 group: / recipient: 확장에 참여해야 할 경우 directory-backed recipient field