Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
338b3cc
fix(clearfolio): fail closed when production is unconfigured
seonghobae Aug 14, 2026
9f223d9
test(clearfolio): prove explicit development and production config bo…
seonghobae Aug 14, 2026
6f9985c
test(clearfolio): enforce signed production and token-origin boundaries
seonghobae Aug 14, 2026
d330ff6
fix(clearfolio): bind viewer tokens to their returned origin
seonghobae Aug 14, 2026
4721551
test(clearfolio): make attachment mock mode explicit
seonghobae Aug 14, 2026
4632000
docs(deploy): make Clearfolio production readiness explicit
seonghobae Aug 14, 2026
45808bf
docs(doctoring): record Clearfolio fail-closed configuration evidence
seonghobae Aug 14, 2026
3facf19
docs(changelog): record Clearfolio production config boundary
seonghobae Aug 14, 2026
928782c
test(clearfolio): cover malformed provider origins
seonghobae Aug 14, 2026
3eecbde
test(clearfolio): cover same-origin viewer token translation
seonghobae Aug 14, 2026
90bd672
test(clearfolio): require 32 non-whitespace HMAC characters
seonghobae Aug 14, 2026
e46dd51
test(clearfolio): prove internal whitespace cannot satisfy secret length
seonghobae Aug 14, 2026
c8da068
fix(clearfolio): count only non-whitespace secret characters
seonghobae Aug 14, 2026
516429f
test(clearfolio): cover IPv6 loopback development URL
seonghobae Aug 14, 2026
5062a8d
fix(clearfolio): recognize IPv6 loopback URL hostname
seonghobae Aug 14, 2026
6cbfc82
merge(clearfolio): reconcile production configuration with protected …
seonghobae Aug 16, 2026
4953fba
test(clearfolio): reject cross-origin artifact tokens
seonghobae Aug 16, 2026
b66180d
fix(clearfolio): reject cross-origin artifact tokens
seonghobae Aug 16, 2026
3834cf2
docs(clearfolio): record fail-closed cross-origin token rule
seonghobae Aug 16, 2026
484dbc0
merge(clearfolio): reconcile protected XML import baseline
seonghobae Aug 16, 2026
d122ca7
docs(deploy): align orchestrator fail-closed contract
seonghobae Aug 16, 2026
b8ebe96
test(clearfolio): fail closed on redirects and foreign artifact links
seonghobae Aug 16, 2026
32e44e4
fix(clearfolio): reject redirect replay and foreign artifact links
seonghobae Aug 16, 2026
95b18d7
docs(clearfolio): record redirect and origin trust boundary
seonghobae Aug 16, 2026
d16d80b
docs(changelog): record Clearfolio redirect hardening
seonghobae Aug 16, 2026
f4432f4
fix(changelog): preserve published release notes
seonghobae Aug 16, 2026
be5a66b
Merge branch 'develop' into fix/clearfolio-production-configuration
opencode-agent[bot] Aug 16, 2026
09ae6d0
merge(develop): reconcile Clearfolio root with OpenCode config
seonghobae Aug 17, 2026
99bc873
Merge branch 'develop' into fix/clearfolio-production-configuration
opencode-agent[bot] Aug 18, 2026
557d345
fix(stack): reconcile Clearfolio configuration with protected develop
seonghobae Aug 20, 2026
78f8b55
chore(stack): reconcile Clearfolio configuration with protected develop
seonghobae Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Security

- Made contextual-orchestrator briefing requests fail closed unless an authenticated endpoint is configured. Deterministic generated text is restricted to explicit `SCOPEWEAVE_DEV=1`, message/provider responses are bounded and validated, and non-loopback HTTP transport is rejected.
- Confined the in-memory Clearfolio adapter to explicit development mode,
required a canonical signed production origin, rejected ambiguous provider
URL components, disabled redirect following on tenant-signed provider calls,
and rejected cross-origin, credential-bearing, or fragmented artifact links
until an explicit reviewed artifact-origin allowlist is configured by a later
slice.
- Made `SCOPEWEAVE_JWT_SECRET` mandatory at startup and rejected weak or
unexpanded placeholder values so production deployments fail closed.
- Neutralized audit-log CSV formulas even when executable prefixes are hidden
Expand Down
25 changes: 20 additions & 5 deletions docs/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,33 @@ persists the database in the `scopeweave-data` volume.
| `SCOPEWEAVE_JWT_SECRET` | **yes** | Signs session JWTs. Startup fails unless it contains at least 32 non-whitespace characters. |
| `PORT` | no (default 8787) | Listen port |
| `SCOPEWEAVE_DB` | no (default `/data/scopeweave.db`) | SQLite file path (on the volume) |
| `SCOPEWEAVE_DEV` | no | Must be `1` to enable the dev `activate-pro` endpoint. **Never set in production.** |
| `SCOPEWEAVE_DEV` | no | Must be `1` to enable development-only behavior, including `activate-pro`, deterministic orchestrator responses, loopback Clearfolio HTTP, and the in-memory Clearfolio adapter when no provider URL exists. **Never set in production.** |
| `STRIPE_SECRET_KEY`, `STRIPE_PRICE_ID`, `STRIPE_WEBHOOK_SECRET` | for live billing | Enables real Stripe Checkout (`npm i stripe` too). Without them, billing uses the mock path. |
| `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_REDIRECT_URI` | for real SSO | Points the OIDC login at your IdP. Unset → a built-in mock IdP (dev/test only). |
| `ORCHESTRATOR_URL` | for AI 브리핑 | contextual-orchestrator 주소. Unset → deterministic mock. |
| `ORCHESTRATOR_TOKEN` | with URL | orchestrator Bearer 토큰 (`CONTEXTUAL_ORCHESTRATOR_TOKEN`). |
| `CLEARFOLIO_URL` | for 산출물 viewer | Clearfolio 문서 뷰어 백엔드 주소. Unset → built-in mock (dev/test). |
| `CLEARFOLIO_HMAC_SECRET` | optional | Signs tenant-claim headers (`clearfolio.tenant-claims.hmac-secret`와 동일 값). |
| `ORCHESTRATOR_URL` | for production AI briefing | Root contextual-orchestrator service origin. Production briefing fails closed when it is absent; deterministic responses exist only with `SCOPEWEAVE_DEV=1`. |
| `ORCHESTRATOR_TOKEN` | with URL | Required bearer token for the configured contextual-orchestrator service (`CONTEXTUAL_ORCHESTRATOR_TOKEN`). |
| `CLEARFOLIO_URL` | for production 산출물 viewer | Root Clearfolio service origin. Production requires HTTPS and rejects credentials, paths, query strings, and fragments. When absent in production, document conversion/viewing is unavailable rather than simulated. |
| `CLEARFOLIO_HMAC_SECRET` | with URL | Required tenant-claim HMAC secret; must contain at least 32 non-whitespace characters and match Clearfolio's configured verifier secret. |
| `SCOPEWEAVE_ATTACHMENT_STATUS_CONCURRENCY` | no (default 8, maximum 32) | Maximum concurrent Clearfolio status lookups during one attachment-list request. Invalid values fall back to 8; values above 32 are clamped. |
| `SCOPEWEAVE_ATTACHMENT_STATUS_TIMEOUT_MS` | no (default 3000, maximum 30000) | Hard caller-side timeout for each Clearfolio status lookup. The AbortSignal is also forwarded downstream. |
| `SCOPEWEAVE_ATTACHMENT_STATUS_BUDGET_MS` | no (default 5000, maximum 60000) | Wall-clock budget for the entire best-effort refresh pass. Work not started before the deadline is deferred to a later list request. |
| `SCOPEWEAVE_RATE_LIMIT_MAX` (+ `SCOPEWEAVE_RATE_LIMIT_WINDOW_MS`) | recommended | Per-IP fixed-window rate limiting (429 + Retry-After). Off when unset. |

### Clearfolio capability readiness

An unset `CLEARFOLIO_URL` is not a successful production conversion service.
Outside explicit `SCOPEWEAVE_DEV=1`, Clearfolio operations fail closed with a
stable configuration error and the mock artifact route is not registered. Other
ScopeWeave planning capabilities remain available. For local integration work,
`SCOPEWEAVE_DEV=1` permits the in-memory adapter when the URL is absent and also
permits HTTP only for `localhost`, `127.0.0.1`, or `::1`; remote HTTP endpoints
are rejected.

Provider URLs are treated as service origins, not arbitrary request prefixes.
Keep credentials in the dedicated HMAC secret setting rather than URL userinfo,
and do not configure a path, query string, or fragment. The adapter constructs
its own versioned API paths from the validated origin.

## Attachment status refresh operations

The attachment-list API reads `job_id` in its initial project-scoped query and
Expand Down
51 changes: 51 additions & 0 deletions docs/doctoring/clearfolio-production-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Clearfolio production configuration boundary

## Decision

ScopeWeave treats Clearfolio as an optional production capability, not as an implicit successful mock. The in-memory converter is available only when `SCOPEWEAVE_DEV=1` and no provider URL is configured. Outside that explicit development boundary, an absent provider produces the stable `clearfolio_not_configured` failure and the mock artifact route is not registered.

A configured production provider must be a root HTTPS origin. ScopeWeave parses the operator value with the platform `URL` implementation and rejects URL credentials, query strings, fragments, and configured paths before building any downstream endpoint. HTTP is limited to explicit development mode on `localhost`, `127.0.0.1`, or `::1`. The tenant-claim HMAC secret is mandatory with a configured provider and must contain at least 32 non-whitespace characters.

This boundary prevents configuration text from becoming an arbitrary downstream request prefix and prevents a production deployment from persisting fake `SUCCEEDED` conversion state merely because an integration is absent. It also preserves independent ScopeWeave operation: planning functionality remains available while document conversion/viewing fails closed with an actionable configuration error.

## Provider redirect and artifact-origin rule

Every tenant-signed submit, status, and artifact-link fetch uses `redirect: "error"`. A provider redirect therefore becomes the existing sanitized transport failure instead of allowing the runtime to replay tenant HMAC headers onto an untrusted `Location` target.

Artifact links returned by this root configuration slice must resolve to the configured Clearfolio origin, must contain no URL credentials, and must contain no fragment. Protocol-relative or absolute foreign-host links fail closed, including token-free links that would otherwise become the browser's attachment-view redirect target. If a same-origin link contains an `artifactToken`, ScopeWeave rewrites that token into the trusted Clearfolio viewer route. A token is never transplanted into another origin.

This root slice deliberately does not invent a cross-origin artifact-host allowlist. A later reviewed policy may admit explicitly configured canonical origins, but until that policy is present the secure default is same-origin only. Issue #489 remains open after this slice. Subsequent bounded work must still add the reviewed artifact-origin allowlist if cross-origin delivery is required, streaming response-size/media-type limits, a provider-wide request budget, and the remaining resource/lifecycle acceptance criteria before the Clearfolio adapter can be described as fully production-complete.

## Executable evidence

`tests/unit/clearfolio-adapter-mock-hmac.test.mjs` proves:

- production without `CLEARFOLIO_URL` does not enable the mock and fails submit/status/artifact operations closed;
- the mock works only under explicit `SCOPEWEAVE_DEV=1`;
- unsupported schemes, remote HTTP, URL credentials, query strings, fragments, configured paths, and weak HMAC secrets are rejected;
- loopback HTTP is accepted only under explicit development mode; and
- signed tenant headers retain the documented canonical HMAC contract.

`tests/unit/clearfolio-status-signal.test.mjs` exercises sanitized transport/HTTP/JSON/status/artifact failures and now requires all three tenant-signed fetch paths to disable redirects. It rejects token-free CDN links, protocol-relative foreign links, credential-bearing same-origin links, fragmented same-origin links, and cross-origin token-bearing links while retaining same-origin relative links and the trusted viewer rewrite. `tests/api/attachment-status.test.mjs` makes its test-only in-memory provider explicit instead of relying on an unset production URL.

The shipped `server/clearfolio.mjs` remains in the canonical c8 production coverage target, so the new configuration branches execute under the repository coverage gate rather than a documentation-only path.

## Standards and threat rationale

The WHATWG URL Standard defines URL components, including credentials, queries, and fragments, and provides the common parsing model used by the JavaScript `URL` API. ScopeWeave parses first and then applies component-level policy instead of relying on string-prefix validation.

OWASP's SSRF Prevention guidance recommends strict allowlisting and warns that redirects and attacker-controlled complete URLs can bypass URL validation. This slice narrows operator configuration to a provider origin, disables redirect following for tenant-signed calls, and keeps browser redirect authority same-origin until an explicit reviewed allowlist exists.

NIST SSDF 1.1 recommends identifying and maintaining software security requirements and producing well-secured software through repeatable verification. The fail-closed configuration contract, executable negative tests, and explicit remaining-gap statement provide acquisition-review evidence without claiming certification.

## Rollback

Rollback reverts the Clearfolio configuration parser, explicit development-mode tests, redirect prohibition, same-origin artifact rule, deployment text, this doctoring record, and the corresponding CHANGELOG entry together. No database schema or persisted attachment representation changes in this slice.

## References

National Institute of Standards and Technology. (2022). *Secure Software Development Framework (SSDF) Version 1.1: Recommendations for mitigating the risk of software vulnerabilities* (NIST Special Publication 800-218). https://doi.org/10.6028/NIST.SP.800-218

OWASP Foundation. (n.d.). *Server Side Request Forgery Prevention Cheat Sheet*. OWASP Cheat Sheet Series. https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html

WHATWG. (2026). *URL Standard*. https://url.spec.whatwg.org/
Loading
Loading