Skip to content

feat(integration): add host-owned plugin delivery-origin authority - #205

Open
seonghobae wants to merge 13 commits into
mainfrom
feat/plugin-delivery-origin-authority-v3
Open

feat(integration): add host-owned plugin delivery-origin authority#205
seonghobae wants to merge 13 commits into
mainfrom
feat/plugin-delivery-origin-authority-v3

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Buyer/security outcome

Advance #130 with an explicit host-owned authority boundary for plugin outbound destinations before any network client is introduced. A plugin manifest remains intent only: it cannot self-authorize an origin.

Scope

  • add versioned life-os.plugin-delivery-origin.v1 grant records scoped to opaque UUIDv4 grant, installation, workspace, and granting user identities;
  • accept only exact normalized HTTPS origins, rejecting credentials, paths, query/fragment content, whitespace/control separators, invalid origins, and port 0;
  • require active installation evidence matching the authenticated workspace/user before any persistence call;
  • make create/replay fail closed on conflicting durable winners;
  • scope lookup and revocation to exact grant + installation + workspace + user authority;
  • validate durable record version, canonical origin, UUIDv4 identities, timestamps, and lifecycle consistency before promoting persistence evidence to application authority.

This slice deliberately does not perform outbound HTTP. DNS/IP rebinding resistance, connect-time address enforcement, redirect/proxy policy, bounded timeouts/bytes, retry/dead-letter, durable PostgreSQL grant storage, and operator HTTP composition remain later #130 slices and must not be inferred as implemented here.

Test-first evidence

The branch preserves RED commit 70ae35d46841da1f33768ff44920605a9c4bffaa, which defines the host delivery-origin authority before the production module exists. Implementation follows in 73958742aa8f6a861bcb34a7e7fbe5922b982ac7.

Exact-head CI/security/review and live-base compatibility remain authoritative; no predecessor evidence transfers.

Summary by CodeRabbit

  • 새로운 기능

    • 플러그인 delivery origin 권한을 생성, 조회 및 폐기할 수 있습니다.
    • HTTPS origin, 설치 정보, workspace·사용자 범위와 권한 상태를 엄격하게 검증합니다.
    • 동일 요청의 재처리를 안전하게 지원하며, 충돌하거나 잘못된 권한 데이터는 거부합니다.
    • 폐기된 권한의 lifecycle 상태를 보존합니다.
  • 테스트

    • 권한 생성·조회·폐기, 멱등성, 범위 검증 및 잘못된 데이터 처리에 대한 테스트를 추가했습니다.

Open in Devin Review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

새로운 PluginDeliveryOriginAuthority 모듈이 HTTPS origin grant의 생성, 조회, 폐기를 구현합니다. 입력, 설치 정보, 저장 레코드 및 durable 결과를 fail-closed 방식으로 검증합니다. 관련 Vitest 테스트가 정상 처리와 오류 처리를 검증합니다.

Changes

플러그인 delivery-origin 권한

Layer / File(s) Summary
권한 계약과 입력 검증
apps/integration-service/src/plugin-delivery-origin-authority.ts
Grant 레코드와 저장소·설치 조회 인터페이스를 추가했습니다. UUID, ISO timestamp, trusted context, HTTPS exact origin 및 저장 레코드를 fail-closed 방식으로 검증합니다.
Grant 생성과 durable 결과 검증
apps/integration-service/src/plugin-delivery-origin-authority.ts, apps/integration-service/src/plugin-delivery-origin-authority.test.ts, apps/integration-service/src/plugin-delivery-origin-authority-evidence.test.ts
활성 설치를 확인한 뒤 origin을 정규화하고 grant를 생성합니다. 멱등 replay, 충돌 및 revoked grant 재사용을 거부합니다. undefinednull durable 결과도 거부합니다.
Grant 조회와 폐기
apps/integration-service/src/plugin-delivery-origin-authority.ts, apps/integration-service/src/plugin-delivery-origin-authority.test.ts
정확한 workspace, 사용자, 설치 및 grant 범위로 grant를 조회합니다. active grant를 원자적으로 폐기하고 revoked 상태와 시각을 검증합니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Mergeability Score: ⚪ Minimal · up to 1e80b

The change adds host-controlled delivery-origin validation and persistence boundaries without introducing outbound network behavior. No actionable merge-blocking risk remains beyond normal review and checks.

Sequence Diagram(s)

sequenceDiagram
  participant PluginDeliveryOriginAuthority
  participant PluginInstallationAuthorityReader
  participant PluginDeliveryOriginGrantStore
  PluginDeliveryOriginAuthority->>PluginInstallationAuthorityReader: 활성 설치 권한 조회
  PluginDeliveryOriginAuthority->>PluginDeliveryOriginGrantStore: 정규화된 HTTPS origin grant 저장
  PluginDeliveryOriginGrantStore-->>PluginDeliveryOriginAuthority: durable grant 반환
  PluginDeliveryOriginAuthority-->>PluginDeliveryOriginAuthority: 반환 결과 검증
Loading

Possibly related PRs

  • ContextualWisdomLab/life-os#191: 공유된 plugin authority와 trusted-context 검증을 사용하지만, 별도의 operator lifecycle 모듈을 수정합니다.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 호스트 소유의 플러그인 delivery-origin 권한 추가라는 변경의 핵심을 정확하고 간결하게 설명합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/plugin-delivery-origin-authority-v3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]

This comment was marked as resolved.

@seonghobae
seonghobae marked this pull request as draft August 14, 2026 08:31
@seonghobae
seonghobae marked this pull request as ready for review August 14, 2026 08:31

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 24e363bf4432de4f7ee8d486285f56064d6c4581.

  • Head SHA: 24e363bf4432de4f7ee8d486285f56064d6c4581

  • Workflow run: 31799111497

  • Workflow attempt: 1

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (4 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (4 files)"]
  R1 --> V1["required checks"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 24e363bf4432de4f7ee8d486285f56064d6c4581
  • Workflow run: 31799111497
  • Workflow attempt: 2
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 24e363bf4432de4f7ee8d486285f56064d6c4581.

  • Head SHA: 24e363bf4432de4f7ee8d486285f56064d6c4581

  • Workflow run: 31799111497

  • Workflow attempt: 2

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (4 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (4 files)"]
  R1 --> V1["required checks"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 24e363bf4432de4f7ee8d486285f56064d6c4581.

  • Head SHA: 24e363bf4432de4f7ee8d486285f56064d6c4581

  • Workflow run: 31799111497

  • Workflow attempt: 2

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (4 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (4 files)"]
  R1 --> V1["required checks"]
Loading

@devin-ai-integration devin-ai-integration 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.

Devin Review found 3 potential issues.

Open in Devin Review

* perform network delivery and therefore does not replace the later DNS/IP,
* redirect, proxy, timeout, byte-limit or connect-time egress enforcement.
*/
export class PluginDeliveryOriginAuthority {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 New authority boundary missing changelog and architecture entry

This PR adds a new host-owned delivery-origin authority boundary but records no Unreleased entry in CHANGELOG.md and nothing in ARCHITECTURE.md, which AGENTS.md requires when a boundary changes. The comparable plugin-installation authority has both.

Prompt for agents
AGENTS.md and CLAUDE.md require CHANGELOG.md and ARCHITECTURE.md to be updated when a service boundary changes. This PR adds a new host-owned plugin delivery-origin authority boundary (apps/integration-service/src/plugin-delivery-origin-authority.ts) but neither file mentions it. Add an entry under CHANGELOG.md's Unreleased > Added describing the delivery-origin grant authority (versioned life-os.plugin-delivery-origin.v1 grants, exact HTTPS-origin validation, active-installation evidence requirement, scoped lookup/revocation), mirroring the existing plugin-installation authority entry, and record the new boundary in ARCHITECTURE.md.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

parsed.pathname !== '/' ||
parsed.search !== '' ||
parsed.hash !== '' ||
parsed.origin === '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.

📝 Info: Unreachable origin==='null' guard

In normalizeOrigin, the parsed.origin === 'null' guard cannot be true once parsed.protocol === 'https:' is required; HTTPS origins are never the string null. Harmless dead code, but it would break the 100% branch-coverage gate AGENTS.md mandates if this package ever runs --coverage (its test script currently does not).

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +221 to +235
function sameActiveGrant(
durable: PluginDeliveryOriginGrantRecord,
candidate: PluginDeliveryOriginGrantRecord,
): boolean {
return (
durable.authorityVersion === candidate.authorityVersion &&
durable.grantId === candidate.grantId &&
durable.installationId === candidate.installationId &&
durable.workspaceId === candidate.workspaceId &&
durable.grantedByUserId === candidate.grantedByUserId &&
durable.origin === candidate.origin &&
durable.status === 'active' &&
durable.revokedAt === 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.

📝 Info: Replay equality intentionally omits grantedAt

sameActiveGrant compares identity plus origin and requires the durable winner to be active, deliberately ignoring grantedAt even though grant computes a fresh one per call. This lets an exact replay succeed and still fails closed on a revoked or origin-conflicting winner. Noted so a future change does not add a grantedAt comparison and break idempotent replay.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

1 participant