Workspace IndexAlgorithms › Day 100

[Final] Write one ADR plus one threat model for your own stack TODO

Algorithms · Day 100 / 100 · G. AI Engineering (Day 97-100)

Concept

An ADR (Architecture Decision Record) briefly documents a single architectural decision — the context, the alternatives considered, the choice and its rationale, and the resulting consequences and accepted trade-offs; accumulating these records over time preserves why the system looks the way it does today. A threat model draws the assets that need protecting and the trust boundaries around them, then for each boundary lists what an attacker can do and what they're after, along with the mitigations and the residual risk that remains. What the two documents share is that they record the premises and the alternatives, not just the conclusion — which means that when a premise changes, there's an automatic signal that the decision needs to be revisited. What matters more than format is keeping the scope narrow — one decision, one system — so the document actually gets read all the way through.

An undocumented decision gets treated, a few months later, as an arbitrary constraint with no reason behind it and gets quietly reversed — and the threat it was blocking comes back to life along with it.

Code & Formula

# [Final] 내 스택의 ADR + 위협 모델 한 편 쓰기 — 코드 대신, 채워 넣기만 하면 되는
# ADR/위협 모델 템플릿을 구조화된 형태로 출력한다 (범위: 결정 하나, 시스템 하나로 좁힐 것).

ADR_TEMPLATE = {
    "title": "결정 제목 (예: '오라클 결과 확정 방식으로 낙관적 제안+이의제기 채택')",
    "context": "왜 이 결정이 필요했는가 — 제약, 요구사항, 지금 상태",
    "alternatives": ["검토한 대안 1과 기각 이유", "검토한 대안 2와 기각 이유"],
    "decision": "실제 선택과 그 근거",
    "consequences": "이 결정으로 생기는 결과와 감수하는 트레이드오프",
}

THREAT_MODEL_TEMPLATE = {
    "asset": "보호해야 할 자산 (예: 사용자 예치금, 오라클 결과값, 개인키)",
    "trust_boundary": "신뢰 경계가 어디인가 (예: 온체인 vs 오프체인, 컨트랙트 vs 오퍼레이터)",
    "attacker_capability": "각 경계에서 공격자가 할 수 있는 것 (예: 트랜잭션 순서 조작, 오라클 값 지연)",
    "mitigation": "대응책 (예: 이의제기 기간, 다중서명, 타임락)",
    "residual_risk": "대응 후에도 남는 위험과, 그 위험을 누가 감수하는가",
}

def print_section(title, template):
    print(f"\n== {title} ==")
    for key, value in template.items():
        if isinstance(value, list):
            print(f"- {key}:")
            for item in value:
                print(f"    · {item}")
        else:
            print(f"- {key}: {value}")

def check_completed(template):
    # 빈 칸(placeholder 그대로) 없이 실제로 채워졌는지 확인하는 게이트
    missing = [k for k, v in template.items() if not v]
    return len(missing) == 0, missing

print_section("ADR 템플릿", ADR_TEMPLATE)
print_section("위협 모델 템플릿", THREAT_MODEL_TEMPLATE)

adr_ok, adr_missing = check_completed(ADR_TEMPLATE)
tm_ok, tm_missing = check_completed(THREAT_MODEL_TEMPLATE)
print(f"\nADR 작성 완료 게이트 통과: {adr_ok} (누락: {adr_missing})")
print(f"위협 모델 작성 완료 게이트 통과: {tm_ok} (누락: {tm_missing})")
print("\n다음 100일 사이클로 넘어가기 전, 실제 값으로 위 두 템플릿을 채운 문서 한 편을 남길 것.")

Exercise

Pick one decision from your own stack that was actually debated, write one ADR for it, then write one threat model for the same component covering assets, trust boundaries, attacker capabilities, mitigations, and residual risk.

Practical Connection

In a prediction market, trust assumptions concentrate around finalizing the oracle's result and settlement authority, so spelling out in a threat model who can change a result and under what conditions a dispute is possible makes both design discussions and audits much easier.

If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.


한국어

[Final] 내 스택의 ADR + 위협 모델 한 편 쓰기 TODO

Algorithms · Day 100 / 100 · G. AI 엔지니어링 (Day 97–100)

개념

ADR(Architecture Decision Record)은 하나의 아키텍처 결정을 맥락, 검토한 대안, 선택과 근거, 그리고 그로 인한 결과와 감수한 트레이드오프로 짧게 기록하는 문서이며, 이런 기록을 시간순으로 누적해 시스템이 왜 지금 모습인지를 보존한다. 위협 모델은 보호해야 할 자산과 신뢰 경계를 그린 뒤, 각 경계에서 공격자가 무엇을 할 수 있고 무엇을 노리는지 열거하고 대응책과 남는 잔여 위험까지 명시하는 문서다. 두 문서의 공통점은 결론만이 아니라 전제와 대안을 남긴다는 점이고, 덕분에 전제가 바뀌면 그 결정을 다시 봐야 한다는 신호가 자동으로 생긴다. 형식보다 중요한 것은 범위를 결정 하나, 시스템 하나로 좁혀 실제로 끝까지 읽히는 분량을 유지하는 것이다.

기록되지 않은 결정은 몇 달 뒤 이유 없는 제약으로 취급되어 조용히 뒤집히고, 그때 그 결정이 막고 있던 위협도 함께 되살아난다.

코드 · 수식

# [Final] 내 스택의 ADR + 위협 모델 한 편 쓰기 — 코드 대신, 채워 넣기만 하면 되는
# ADR/위협 모델 템플릿을 구조화된 형태로 출력한다 (범위: 결정 하나, 시스템 하나로 좁힐 것).

ADR_TEMPLATE = {
    "title": "결정 제목 (예: '오라클 결과 확정 방식으로 낙관적 제안+이의제기 채택')",
    "context": "왜 이 결정이 필요했는가 — 제약, 요구사항, 지금 상태",
    "alternatives": ["검토한 대안 1과 기각 이유", "검토한 대안 2와 기각 이유"],
    "decision": "실제 선택과 그 근거",
    "consequences": "이 결정으로 생기는 결과와 감수하는 트레이드오프",
}

THREAT_MODEL_TEMPLATE = {
    "asset": "보호해야 할 자산 (예: 사용자 예치금, 오라클 결과값, 개인키)",
    "trust_boundary": "신뢰 경계가 어디인가 (예: 온체인 vs 오프체인, 컨트랙트 vs 오퍼레이터)",
    "attacker_capability": "각 경계에서 공격자가 할 수 있는 것 (예: 트랜잭션 순서 조작, 오라클 값 지연)",
    "mitigation": "대응책 (예: 이의제기 기간, 다중서명, 타임락)",
    "residual_risk": "대응 후에도 남는 위험과, 그 위험을 누가 감수하는가",
}

def print_section(title, template):
    print(f"\n== {title} ==")
    for key, value in template.items():
        if isinstance(value, list):
            print(f"- {key}:")
            for item in value:
                print(f"    · {item}")
        else:
            print(f"- {key}: {value}")

def check_completed(template):
    # 빈 칸(placeholder 그대로) 없이 실제로 채워졌는지 확인하는 게이트
    missing = [k for k, v in template.items() if not v]
    return len(missing) == 0, missing

print_section("ADR 템플릿", ADR_TEMPLATE)
print_section("위협 모델 템플릿", THREAT_MODEL_TEMPLATE)

adr_ok, adr_missing = check_completed(ADR_TEMPLATE)
tm_ok, tm_missing = check_completed(THREAT_MODEL_TEMPLATE)
print(f"\nADR 작성 완료 게이트 통과: {adr_ok} (누락: {adr_missing})")
print(f"위협 모델 작성 완료 게이트 통과: {tm_ok} (누락: {tm_missing})")
print("\n다음 100일 사이클로 넘어가기 전, 실제 값으로 위 두 템플릿을 채운 문서 한 편을 남길 것.")

연습

자기 스택에서 논쟁이 있었던 결정 하나를 골라 ADR 한 장을 쓰고, 같은 컴포넌트에 대해 자산·신뢰 경계·공격자 능력·대응책·잔여 위험을 담은 위협 모델 한 장을 이어서 작성하라.

실무 · Verex 연결

예측시장에서는 오라클 결과 확정과 정산 권한에 신뢰 가정이 집중되므로, 누가 결과를 바꿀 수 있고 어떤 조건에서 분쟁이 가능한지를 위협 모델로 명시해 두면 설계 논의와 감사 대응이 모두 수월해진다.

공부한 날 원본 커리큘럼(docs/knowledge/dev-100-curriculum.md)의 이 줄에 노트 링크와 ✅ 를 붙이면, 이 자리는 노트 본문으로 바로 이어집니다. 노트 없이 이 페이지에 바로 적어도 됩니다 — 다만 다시 생성하면 덮어쓰이므로, 남길 글은 docs/algorithms/ 의 마크다운으로 쓰는 편이 안전합니다.

← 99. 에이전트 루프 설계