Skip to content

feat(workflow): 다중 운영자 — 레지스트리 + decidedBy 신원 강제 - #57

Merged
redsunjin merged 2 commits into
mainfrom
feat/workflow-multi-operator
Aug 5, 2026
Merged

feat(workflow): 다중 운영자 — 레지스트리 + decidedBy 신원 강제#57
redsunjin merged 2 commits into
mainfrom
feat/workflow-multi-operator

Conversation

@redsunjin

Copy link
Copy Markdown
Owner

요약

마지막 예약 스펙 구현. 스펙: docs/superpowers/specs/2026-08-04-workflow-multi-operator-design.md

  • 권한 분리: root(서버 토큰)=관리 전용(actor/운영자 등록·폐기·목록), 결정·조회는 개별 운영자 토큰 — POST /api/operators/register(upsert=토큰 회전, sha256 해시 저장), GET /api/operators, POST /api/operators/:id/revoke.
  • 신원 기록: 엄격 모드에서 decidedBy를 토큰 신원(root/operatorId)으로 강제 — body 위조 무시, 이력에 실제 결정자가 남는다. open 모드는 현행 유지.
  • WS: 운영자 토큰도 WORKFLOW_AUTH로 전체 스트림 구독(AUTH_OK에 operatorId), revoke 시 소켓 4401(OPERATOR_REVOKED) 즉시 종료.
  • 대시보드 무변경: 토큰 게이트에 운영자 토큰을 넣으면 HTTP·WS 모두 그대로 동작.
  • 기존 history 테스트는 의도된 동작 변화(서버 토큰 결정 → decidedBy 'root')에 맞게 기대값 갱신.

테스트

신규 4건(신원 강제·위조 무시 / 관리 라우트 root 전용 / WS 전체 스트림+revoke 4401·root 소켓 유지 / 재시작 후 토큰 유효) — 전체 서버 32 + UI 29 통과.

경계

workflow/ + docs만 수정. RBAC/승인선은 후속.

🤖 Generated with Claude Code

selimDGAX and others added 2 commits August 5, 2026 12:11
root(서버 토큰)는 관리 전용으로 분리하고, 결정·조회(pending 목록,
decide, history, chain)와 WS 전체 스트림은 개별 운영자 토큰으로
수행한다. 엄격 모드에선 decidedBy가 토큰 신원(root/operatorId)으로
강제되어 body 위조가 불가능하다. revoke 시 해당 운영자 소켓 4401
즉시 종료 + 토큰 무효화, sha256 해시 저장·재등록 토큰 회전·영속화는
actor 레지스트리 패턴 그대로. 기존 history 테스트는 신원 강제에 맞게
기대값(root) 갱신.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 24a064dc9e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread workflow/server.js
sendJson(res, error?.code === 'BODY_TOO_LARGE' ? 413 : 400, { error: error?.code || 'Invalid JSON body' });
return;
}
const registered = registerOperator(data);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Close old operator sockets when rotating tokens

When this register endpoint is used as the documented upsert/token-rotation path for an existing operator, the old token is invalidated for future HTTP auth but any WebSocket that already authenticated with that old token stays isAuthorized and continues receiving the full operator stream because only the revoke route calls closeOperatorSockets. In strict mode this means rotating a leaked operator token does not actually remove live access until the stale socket disconnects, so the existing operator's sockets should be closed as part of rotation.

Useful? React with 👍 / 👎.

Comment on lines +35 to +36
const id = sanitizeText(operatorId, 80);
if (!id) return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject the reserved root operator id

Because root is the server-token identity, allowing an operator to register with operatorId: 'root' makes that operator's decisions audit as decidedBy: 'root' and also collides with server-token WebSocket bookkeeping when /api/operators/root/revoke closes operator sockets by id. In strict mode this breaks the identity boundary and can close root dashboard sockets, so the registry should reserve/reject this id.

Useful? React with 👍 / 👎.

@redsunjin
redsunjin merged commit 96e9005 into main Aug 5, 2026
4 checks passed
@redsunjin
redsunjin deleted the feat/workflow-multi-operator branch August 5, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants