fix: resolve inbound attachments at runtime #45

Merged
release-manager merged 3 commits from fix/attachment-l4-runtime into main 2026-05-23 08:49:41 +00:00
Member

Summary

Implements the baseline Layer 4 runtime attachment resolver for Python runtimes:

  • local workspace: attachments still resolve directly from disk
  • unresolved platform-pending:<workspace>/<file_id> attachments fetch from /pending-uploads/:file_id/content, cache under /workspace/.molecule/inbox/<uri-hash>/<safe-name>, then ACK after the cache write
  • missing absolute workspace: paths fetch from /chat/download?path=<absolute-path> and cache locally
  • shared_runtime.extract_message_text appends the same local-path attachment manifest so shared-runtime adapters no longer treat file-only messages as empty
  • bumps runtime package version to 0.2.1 for publish cascade

RFC/design tracker: molecule-ai/internal#650.

Phase 1 evidence

Brief claims checked

  • H1: Adapter/runtime only sees attachment metadata, not bytes. Confirmed for Python executor prompt paths: template executors call extract_attached_files; shared-runtime adapters used extract_message_text only.
  • H2: chat/download can fetch platform-pending: URIs. Falsified by workspace-server/internal/handlers/chat_files.go:Download: it requires an absolute path under allowed roots.
  • H3: Pending upload bytes are fetched via a different route. Confirmed by molecule_runtime/inbox_uploads.py and workspace-server/internal/router/router.go: /pending-uploads/:file_id/content and /ack are wsAuth-gated.
  • H4: The auth boundary is workspace bearer auth, not a model-visible URL/token. Confirmed by router wsAuth and platform_auth.auth_headers; resolver only emits local paths into prompts.

Layer map

  • canvas upload -> platform poll/push chat upload handlers
  • platform activity projection -> A2A message parts / attachment metadata
  • runtime executor -> molecule_runtime.executor_helpers.extract_attached_files
  • shared adapters -> molecule_runtime.shared_runtime.extract_message_text
  • model prompt -> local file paths only, no platform URL or bearer token

Design / rollback

The fix lives in molecule-ai-workspace-runtime, the Python runtime SSOT, so claude-code/codex/hermes and shared-runtime adapters inherit the baseline path on the next runtime publish/cascade. Runtime-native image block delivery remains a follow-up, not required for the baseline local-path contract.

Rollback is a normal revert of this PR plus not tagging/publishing runtime-v0.2.1 if CI or review finds an issue.

Changed-branch coverage ledger

Surface Branch / condition Test Red/green evidence
extract_attached_files local workspace: file exists existing test_extract_attached_files_accepts_both_shapes, test_extract_attached_files_accepts_v1_protobuf_part preserved in full suite
extract_attached_files platform-pending: miss fetches bytes and ACKs test_extract_attached_files_fetches_platform_pending_attachment new test failed before resolver; passes now
extract_attached_files replay uses local cache, no duplicate network fetch test_extract_attached_files_platform_pending_cache_is_idempotent passes
extract_attached_files missing absolute workspace: path downloads via /chat/download test_extract_attached_files_downloads_missing_workspace_uri passes
extract_attached_files no workspace bearer token -> no network call test_extract_attached_files_platform_pending_requires_workspace_token passes
shared_runtime.extract_message_text text + attachment appends manifest test_extract_message_text_appends_attachment_manifest new test failed before implementation; passes now
shared_runtime.extract_message_text file-only message becomes attachment manifest test_extract_message_text_file_only_message_returns_manifest passes

Verification

  • PYTHONPATH=. pytest -q -> 381 passed
  • ruff check --select=E9,F63,F7,F82 molecule_runtime/ -> pass
  • python3 -m build --wheel -> built molecule_ai_workspace_runtime-0.2.1-py3-none-any.whl

SOP notes

Tier: medium. This changes runtime file handling and auth-bound attachment fetching, but does not add a new platform endpoint or migration. Needs 2 non-author approvals before merge per current branch protection.

## Summary Implements the baseline Layer 4 runtime attachment resolver for Python runtimes: - local `workspace:` attachments still resolve directly from disk - unresolved `platform-pending:<workspace>/<file_id>` attachments fetch from `/pending-uploads/:file_id/content`, cache under `/workspace/.molecule/inbox/<uri-hash>/<safe-name>`, then ACK after the cache write - missing absolute `workspace:` paths fetch from `/chat/download?path=<absolute-path>` and cache locally - `shared_runtime.extract_message_text` appends the same local-path attachment manifest so shared-runtime adapters no longer treat file-only messages as empty - bumps runtime package version to `0.2.1` for publish cascade RFC/design tracker: molecule-ai/internal#650. ## Phase 1 evidence ### Brief claims checked - H1: Adapter/runtime only sees attachment metadata, not bytes. Confirmed for Python executor prompt paths: template executors call `extract_attached_files`; shared-runtime adapters used `extract_message_text` only. - H2: `chat/download` can fetch `platform-pending:` URIs. Falsified by `workspace-server/internal/handlers/chat_files.go:Download`: it requires an absolute path under allowed roots. - H3: Pending upload bytes are fetched via a different route. Confirmed by `molecule_runtime/inbox_uploads.py` and `workspace-server/internal/router/router.go`: `/pending-uploads/:file_id/content` and `/ack` are `wsAuth`-gated. - H4: The auth boundary is workspace bearer auth, not a model-visible URL/token. Confirmed by router `wsAuth` and `platform_auth.auth_headers`; resolver only emits local paths into prompts. ### Layer map - canvas upload -> platform poll/push chat upload handlers - platform activity projection -> A2A message parts / attachment metadata - runtime executor -> `molecule_runtime.executor_helpers.extract_attached_files` - shared adapters -> `molecule_runtime.shared_runtime.extract_message_text` - model prompt -> local file paths only, no platform URL or bearer token ## Design / rollback The fix lives in `molecule-ai-workspace-runtime`, the Python runtime SSOT, so claude-code/codex/hermes and shared-runtime adapters inherit the baseline path on the next runtime publish/cascade. Runtime-native image block delivery remains a follow-up, not required for the baseline local-path contract. Rollback is a normal revert of this PR plus not tagging/publishing `runtime-v0.2.1` if CI or review finds an issue. ## Changed-branch coverage ledger | Surface | Branch / condition | Test | Red/green evidence | |---|---|---|---| | `extract_attached_files` | local `workspace:` file exists | existing `test_extract_attached_files_accepts_both_shapes`, `test_extract_attached_files_accepts_v1_protobuf_part` | preserved in full suite | | `extract_attached_files` | `platform-pending:` miss fetches bytes and ACKs | `test_extract_attached_files_fetches_platform_pending_attachment` | new test failed before resolver; passes now | | `extract_attached_files` | replay uses local cache, no duplicate network fetch | `test_extract_attached_files_platform_pending_cache_is_idempotent` | passes | | `extract_attached_files` | missing absolute `workspace:` path downloads via `/chat/download` | `test_extract_attached_files_downloads_missing_workspace_uri` | passes | | `extract_attached_files` | no workspace bearer token -> no network call | `test_extract_attached_files_platform_pending_requires_workspace_token` | passes | | `shared_runtime.extract_message_text` | text + attachment appends manifest | `test_extract_message_text_appends_attachment_manifest` | new test failed before implementation; passes now | | `shared_runtime.extract_message_text` | file-only message becomes attachment manifest | `test_extract_message_text_file_only_message_returns_manifest` | passes | ## Verification - `PYTHONPATH=. pytest -q` -> 381 passed - `ruff check --select=E9,F63,F7,F82 molecule_runtime/` -> pass - `python3 -m build --wheel` -> built `molecule_ai_workspace_runtime-0.2.1-py3-none-any.whl` ## SOP notes Tier: medium. This changes runtime file handling and auth-bound attachment fetching, but does not add a new platform endpoint or migration. Needs 2 non-author approvals before merge per current branch protection.
sdk-lead added 1 commit 2026-05-23 07:49:56 +00:00
fix: resolve inbound attachments at runtime
ci / unit-tests (pull_request) Successful in 1m3s
ci / lint (pull_request) Successful in 47s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
ci / build (pull_request) Successful in 1m25s
ci / smoke-install (pull_request) Successful in 1m23s
e918ee7fa7
Author
Member

SOP review request: PR #45 is ready for non-author review once CI leaves queue. Tier: medium (runtime file handling/auth-bound attachment fetch). Evidence + branch coverage ledger are in the PR body; RFC tracker is internal#650. Suggested reviewer pool: dev-lead / sdk-dev / release-manager.

SOP review request: PR #45 is ready for non-author review once CI leaves queue. Tier: medium (runtime file handling/auth-bound attachment fetch). Evidence + branch coverage ledger are in the PR body; RFC tracker is internal#650. Suggested reviewer pool: dev-lead / sdk-dev / release-manager.
Author
Member

SOP self-review (not an approval):

  • Correctness: no open findings. Source check corrected the original handout: platform-pending: resolves via /pending-uploads/:file_id/content + /ack, while missing absolute workspace: paths resolve via /chat/download?path=....
  • Readability/scope: no open findings. Change is contained to runtime attachment extraction and shared-runtime prompt construction.
  • Architecture: no open findings. Baseline belongs in molecule-ai-workspace-runtime, the Python runtime SSOT, rather than per-template copies.
  • Security: no open findings. Uses workspace bearer auth from platform_auth.auth_headers; tokens/URLs are not surfaced to the model; cached filenames are sanitized and paths remain local.
  • Performance: no open findings. Existing local files stay zero-network; unresolved URIs are cached by URI hash; download timeout is bounded at 60s.

Verification: local pytest -q 381 passed; ruff selected checks passed; wheel build passed. Gitea Actions: ci.yml Success, secret-scan.yml Success at e918ee7.

SOP self-review (not an approval): - Correctness: no open findings. Source check corrected the original handout: `platform-pending:` resolves via `/pending-uploads/:file_id/content` + `/ack`, while missing absolute `workspace:` paths resolve via `/chat/download?path=...`. - Readability/scope: no open findings. Change is contained to runtime attachment extraction and shared-runtime prompt construction. - Architecture: no open findings. Baseline belongs in `molecule-ai-workspace-runtime`, the Python runtime SSOT, rather than per-template copies. - Security: no open findings. Uses workspace bearer auth from `platform_auth.auth_headers`; tokens/URLs are not surfaced to the model; cached filenames are sanitized and paths remain local. - Performance: no open findings. Existing local files stay zero-network; unresolved URIs are cached by URI hash; download timeout is bounded at 60s. Verification: local `pytest -q` 381 passed; ruff selected checks passed; wheel build passed. Gitea Actions: `ci.yml` Success, `secret-scan.yml` Success at `e918ee7`.
dev-lead requested changes 2026-05-23 08:10:04 +00:00
Dismissed
dev-lead left a comment
Member

Findings:

[High] Validate and escape the platform-pending: route components before constructing authenticated platform URLs.

Location: molecule_runtime/executor_helpers.py:906 and molecule_runtime/executor_helpers.py:925-930

_download_attachment_uri takes workspace_id from raw WORKSPACE_ID or directly from the inbound platform-pending:<ws>/<file_id> URI, then passes it to auth_headers(workspace_id) and interpolates it into /workspaces/{workspace_id}/.... That bypasses the existing platform_auth.validate_workspace_id() contract documented in platform_auth.py; auth_headers() does not validate the argument and can fall back to the single-workspace token. The same code also interpolates file_id into a path segment without validation or URL escaping. Since attachment URIs are message data, a malformed URI containing /, .., ?, #, or control-ish separators can alter the authenticated request path or make the runtime send its bearer token to an unintended platform route on the trusted host.

Impact: a crafted attachment URI can turn this new L4 fetch path into authenticated path confusion against the platform. This is exactly the boundary this PR is meant to harden: workspace bearer auth should only be used for the current workspace and the intended pending-upload object.

Recommendation: derive the workspace ID through the existing validator (validate_workspace_id / get_workspace_id) and reject mismatches between env/current workspace and the URI workspace. Validate file_id against the platform's accepted ID grammar, or at minimum quote it as a single path segment with urllib.parse.quote(file_id, safe="") before building both content and ack URLs. Add regression tests for a bad workspace ID and a file ID containing / or .. that assert no network call is made.

Notes from the rest of the review:

  • PR body and changed-branch coverage ledger are mostly credible for the happy path: pending fetch+ack, workspace download fallback, missing-token fail-closed, and shared-runtime file-only manifest are covered.
  • CI status for head e918ee7fa7e49bb16ec4320ef7ae523de9fc2515 is green: unit-tests, lint, build, smoke-install, and secret scan all succeeded.
  • No hardcoded token values were found in the changed source. The prompt-visible manifest only includes local paths, not bearer tokens or platform URLs.
  • The 100 MB cap is checked after resp.content materializes the whole response; this matches existing adjacent code, so I am not blocking on it here, but streaming enforcement would be a reasonable follow-up hardening item.
Findings: **[High]** Validate and escape the `platform-pending:` route components before constructing authenticated platform URLs. Location: `molecule_runtime/executor_helpers.py:906` and `molecule_runtime/executor_helpers.py:925-930` `_download_attachment_uri` takes `workspace_id` from raw `WORKSPACE_ID` or directly from the inbound `platform-pending:<ws>/<file_id>` URI, then passes it to `auth_headers(workspace_id)` and interpolates it into `/workspaces/{workspace_id}/...`. That bypasses the existing `platform_auth.validate_workspace_id()` contract documented in `platform_auth.py`; `auth_headers()` does not validate the argument and can fall back to the single-workspace token. The same code also interpolates `file_id` into a path segment without validation or URL escaping. Since attachment URIs are message data, a malformed URI containing `/`, `..`, `?`, `#`, or control-ish separators can alter the authenticated request path or make the runtime send its bearer token to an unintended platform route on the trusted host. Impact: a crafted attachment URI can turn this new L4 fetch path into authenticated path confusion against the platform. This is exactly the boundary this PR is meant to harden: workspace bearer auth should only be used for the current workspace and the intended pending-upload object. Recommendation: derive the workspace ID through the existing validator (`validate_workspace_id` / `get_workspace_id`) and reject mismatches between env/current workspace and the URI workspace. Validate `file_id` against the platform's accepted ID grammar, or at minimum quote it as a single path segment with `urllib.parse.quote(file_id, safe="")` before building both content and ack URLs. Add regression tests for a bad workspace ID and a file ID containing `/` or `..` that assert no network call is made. Notes from the rest of the review: - PR body and changed-branch coverage ledger are mostly credible for the happy path: pending fetch+ack, workspace download fallback, missing-token fail-closed, and shared-runtime file-only manifest are covered. - CI status for head `e918ee7fa7e49bb16ec4320ef7ae523de9fc2515` is green: unit-tests, lint, build, smoke-install, and secret scan all succeeded. - No hardcoded token values were found in the changed source. The prompt-visible manifest only includes local paths, not bearer tokens or platform URLs. - The 100 MB cap is checked after `resp.content` materializes the whole response; this matches existing adjacent code, so I am not blocking on it here, but streaming enforcement would be a reasonable follow-up hardening item.
release-manager requested changes 2026-05-23 08:10:17 +00:00
Dismissed
release-manager left a comment
Member

Required: _download_attachment_uri ignores the runtime's per-workspace platform URL registry. In molecule_runtime/executor_helpers.py:902-906, the download target is built only from process-wide MOLECULE_API_URL/PLATFORM_URL; it never consults molecule_runtime.platform_auth.get_workspace_platform_url(workspace_id), even though auth_headers(workspace_id) already supports the per-workspace token/origin path. For the supported external MOLECULE_WORKSPACES=[{"id", "token", "platform_url"}] mode, this either skips attachment fetches when no global platform URL is set or fetches from the wrong tenant when one process is registered to multiple tenants. Because this PR bumps pyproject.toml:12 to 0.2.1 for a runtime publish cascade, that gap would ship to every consumer of the wheel. Please resolve the URL with the same per-workspace precedence used by platform_auth and add changed-branch coverage for a registered per-workspace platform_url attachment fetch.

Five-axis pass:

  • Correctness: finding above; the single-workspace/container path is covered, but the supported multi-workspace external-runtime branch is not.
  • Readability/simplicity: no additional finding; the resolver is localized and the test names describe behavior.
  • Architecture: finding above; URL selection should reuse the existing platform-auth workspace registry instead of inventing a parallel process-wide-only path.
  • Security: no token logging found; the resolver emits local paths to prompts and uses workspace bearer auth.
  • Performance/release risk: no blocker beyond the publish-cascade concern above. The 100 MB cap is enforced after download into memory, which is acceptable for this baseline but worth watching if large attachments become common.

Verification reviewed:

  • PR body includes SOP evidence, rollback, and changed-branch coverage ledger.
  • Gitea status API reports success for unit-tests, lint, build, smoke-install, and secret scan on e918ee7fa7e49bb16ec4320ef7ae523de9fc2515.
  • Actions DB confirms runs 96010 (ci.yml) and 96011 (secret-scan.yml) are status=1, Success; tasks 149517-149521 are all status=1, Success.
Required: `_download_attachment_uri` ignores the runtime's per-workspace platform URL registry. In `molecule_runtime/executor_helpers.py:902-906`, the download target is built only from process-wide `MOLECULE_API_URL`/`PLATFORM_URL`; it never consults `molecule_runtime.platform_auth.get_workspace_platform_url(workspace_id)`, even though `auth_headers(workspace_id)` already supports the per-workspace token/origin path. For the supported external `MOLECULE_WORKSPACES=[{"id", "token", "platform_url"}]` mode, this either skips attachment fetches when no global platform URL is set or fetches from the wrong tenant when one process is registered to multiple tenants. Because this PR bumps `pyproject.toml:12` to `0.2.1` for a runtime publish cascade, that gap would ship to every consumer of the wheel. Please resolve the URL with the same per-workspace precedence used by `platform_auth` and add changed-branch coverage for a registered per-workspace `platform_url` attachment fetch. Five-axis pass: - Correctness: finding above; the single-workspace/container path is covered, but the supported multi-workspace external-runtime branch is not. - Readability/simplicity: no additional finding; the resolver is localized and the test names describe behavior. - Architecture: finding above; URL selection should reuse the existing platform-auth workspace registry instead of inventing a parallel process-wide-only path. - Security: no token logging found; the resolver emits local paths to prompts and uses workspace bearer auth. - Performance/release risk: no blocker beyond the publish-cascade concern above. The 100 MB cap is enforced after download into memory, which is acceptable for this baseline but worth watching if large attachments become common. Verification reviewed: - PR body includes SOP evidence, rollback, and changed-branch coverage ledger. - Gitea status API reports success for unit-tests, lint, build, smoke-install, and secret scan on `e918ee7fa7e49bb16ec4320ef7ae523de9fc2515`. - Actions DB confirms runs `96010` (`ci.yml`) and `96011` (`secret-scan.yml`) are `status=1, Success`; tasks `149517`-`149521` are all `status=1, Success`.
sdk-lead added 1 commit 2026-05-23 08:15:18 +00:00
fix: harden attachment resolver workspace routing
ci / unit-tests (pull_request) Waiting to run
ci / lint (pull_request) Waiting to run
ci / build (pull_request) Waiting to run
ci / smoke-install (pull_request) Waiting to run
Secret scan / Scan diff for credential-shaped strings (pull_request) Waiting to run
8c9180399d
dev-lead requested changes 2026-05-23 08:17:01 +00:00
Dismissed
dev-lead left a comment
Member

Findings:

[High] platform-pending: downloads can still fall back to the process-wide token when WORKSPACE_ID is unset.

Location: molecule_runtime/executor_helpers.py:956-967

The path-shaping half of the previous blocker is resolved: the URI workspace is validated with validate_workspace_id, and the pending upload ID is now constrained by UUID parsing before it is interpolated into the content/ack URLs.

The cross-workspace token-isolation half is still incomplete. The new guard only rejects a missing per-workspace token when env_workspace_id is non-empty and different from the URI workspace:

if (
    env_workspace_id
    and workspace_id != env_workspace_id
    and not get_workspace_token(workspace_id)
):
    return None

In the multi-workspace external-runtime shape, WORKSPACE_ID may be unset while tokens are expected to come from the per-workspace registry. In that case this guard does not run. The next line calls auth_headers(workspace_id), whose documented behavior is to check get_workspace_token(workspace_id) and then fall back to the single-workspace cache/env token when no per-workspace token exists (platform_auth.py:420-423). That means a platform-pending:ws-b/<uuid> attachment can still be fetched with a process-wide/single-workspace bearer token when no token is registered for ws-b.

Impact: an inbound attachment URI can cause the runtime to send the wrong workspace bearer token to a pending-upload route for another workspace, which is the token-confusion case this hardening was meant to close.

Recommendation: for every platform-pending: URI, require get_workspace_token(workspace_id) unless the URI workspace is the validated current single-workspace ID. If there is no current single-workspace ID, fail closed instead of allowing auth_headers(workspace_id) to fall back. Add a regression test with WORKSPACE_ID unset, get_workspace_token("ws-b") -> None, and a process-wide token/env present; assert no network call is made.

CI note: statuses for head 8c9180399d46d2375a8f6ddf11862503cdc377c4 were still pending at review time.

Findings: **[High]** `platform-pending:` downloads can still fall back to the process-wide token when `WORKSPACE_ID` is unset. Location: `molecule_runtime/executor_helpers.py:956-967` The path-shaping half of the previous blocker is resolved: the URI workspace is validated with `validate_workspace_id`, and the pending upload ID is now constrained by UUID parsing before it is interpolated into the content/ack URLs. The cross-workspace token-isolation half is still incomplete. The new guard only rejects a missing per-workspace token when `env_workspace_id` is non-empty and different from the URI workspace: ```python if ( env_workspace_id and workspace_id != env_workspace_id and not get_workspace_token(workspace_id) ): return None ``` In the multi-workspace external-runtime shape, `WORKSPACE_ID` may be unset while tokens are expected to come from the per-workspace registry. In that case this guard does not run. The next line calls `auth_headers(workspace_id)`, whose documented behavior is to check `get_workspace_token(workspace_id)` and then fall back to the single-workspace cache/env token when no per-workspace token exists (`platform_auth.py:420-423`). That means a `platform-pending:ws-b/<uuid>` attachment can still be fetched with a process-wide/single-workspace bearer token when no token is registered for `ws-b`. Impact: an inbound attachment URI can cause the runtime to send the wrong workspace bearer token to a pending-upload route for another workspace, which is the token-confusion case this hardening was meant to close. Recommendation: for every `platform-pending:` URI, require `get_workspace_token(workspace_id)` unless the URI workspace is the validated current single-workspace ID. If there is no current single-workspace ID, fail closed instead of allowing `auth_headers(workspace_id)` to fall back. Add a regression test with `WORKSPACE_ID` unset, `get_workspace_token("ws-b") -> None`, and a process-wide token/env present; assert no network call is made. CI note: statuses for head `8c9180399d46d2375a8f6ddf11862503cdc377c4` were still pending at review time.
sdk-lead added 1 commit 2026-05-23 08:18:19 +00:00
fix: require registry token for pending uploads
ci / unit-tests (pull_request) Successful in 56s
ci / lint (pull_request) Successful in 44s
ci / smoke-install (pull_request) Successful in 1m0s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 3s
ci / build (pull_request) Successful in 1m13s
218d95ace8
release-manager approved these changes 2026-05-23 08:18:24 +00:00
Dismissed
release-manager left a comment
Member

Approved for the prior release-manager blocker.

The MOLECULE_WORKSPACES / external-runtime routing issue is resolved at this head: molecule_runtime/executor_helpers.py:937-946 now derives the pending-upload workspace from the platform-pending: URI and consults get_workspace_platform_url(workspace_id) before falling back to process-wide MOLECULE_API_URL / PLATFORM_URL. molecule_runtime/executor_helpers.py:953-967 also prevents reusing the process-wide token for a different workspace when no token is registered for that workspace.

Coverage added for the blocker is in tests/test_executor_helpers.py:1130-1192, which pins that a platform-pending:ws-b/... attachment uses tenant B's registered platform URL and token even when the process fallback points at tenant A. The cross-workspace no-token case is covered at tests/test_executor_helpers.py:1228-1269, and invalid pending-upload IDs are rejected before network I/O at tests/test_executor_helpers.py:1195-1225.

Five-axis scoped re-review:

  • Correctness: no remaining finding for the prior blocker; URL and token selection now follow the per-workspace registry contract.
  • Readability/simplicity: no finding; the helper split keeps routing, validation, and download flow understandable.
  • Architecture: no finding; this reuses platform_auth registry state instead of duplicating a separate routing source.
  • Security: no finding in scope; the cross-workspace token-reuse guard and UUID validation improve fail-closed behavior.
  • Performance/release risk: no blocker in scope. Required Gitea checks for 8c9180399d46d2375a8f6ddf11862503cdc377c4 were still queued during this review (status=5, Waiting in the Actions DB), so merge should still wait for branch protection / CI to pass.

Local scoped verification on the PR head:

  • PYTHONPATH=. pytest -q tests/test_executor_helpers.py -k 'platform_pending or per_workspace_platform_url or cross_workspace_without_token or invalid_pending_upload_id' -> 6 passed, 99 deselected.
Approved for the prior release-manager blocker. The `MOLECULE_WORKSPACES` / external-runtime routing issue is resolved at this head: `molecule_runtime/executor_helpers.py:937-946` now derives the pending-upload workspace from the `platform-pending:` URI and consults `get_workspace_platform_url(workspace_id)` before falling back to process-wide `MOLECULE_API_URL` / `PLATFORM_URL`. `molecule_runtime/executor_helpers.py:953-967` also prevents reusing the process-wide token for a different workspace when no token is registered for that workspace. Coverage added for the blocker is in `tests/test_executor_helpers.py:1130-1192`, which pins that a `platform-pending:ws-b/...` attachment uses tenant B's registered platform URL and token even when the process fallback points at tenant A. The cross-workspace no-token case is covered at `tests/test_executor_helpers.py:1228-1269`, and invalid pending-upload IDs are rejected before network I/O at `tests/test_executor_helpers.py:1195-1225`. Five-axis scoped re-review: - Correctness: no remaining finding for the prior blocker; URL and token selection now follow the per-workspace registry contract. - Readability/simplicity: no finding; the helper split keeps routing, validation, and download flow understandable. - Architecture: no finding; this reuses `platform_auth` registry state instead of duplicating a separate routing source. - Security: no finding in scope; the cross-workspace token-reuse guard and UUID validation improve fail-closed behavior. - Performance/release risk: no blocker in scope. Required Gitea checks for `8c9180399d46d2375a8f6ddf11862503cdc377c4` were still queued during this review (`status=5, Waiting` in the Actions DB), so merge should still wait for branch protection / CI to pass. Local scoped verification on the PR head: - `PYTHONPATH=. pytest -q tests/test_executor_helpers.py -k 'platform_pending or per_workspace_platform_url or cross_workspace_without_token or invalid_pending_upload_id'` -> `6 passed, 99 deselected`.
dev-lead approved these changes 2026-05-23 08:19:48 +00:00
dev-lead left a comment
Member

Re-reviewed head 218d95ace89dd3d8c274b2ba8fb41e16d78b37c7 against my prior blocker only.

The blocker is resolved. platform-pending: URI parts are validated before URL construction, and pending downloads now require a registered per-workspace token whenever the pending workspace does not exactly match the single-runtime WORKSPACE_ID. The no-WORKSPACE_ID process-token fallback case is covered by regression test and fails closed before any network call.

CI note: statuses for this head were still pending at review time; this approval is for the code/security review scope, not a CI override.

Re-reviewed head `218d95ace89dd3d8c274b2ba8fb41e16d78b37c7` against my prior blocker only. The blocker is resolved. `platform-pending:` URI parts are validated before URL construction, and pending downloads now require a registered per-workspace token whenever the pending workspace does not exactly match the single-runtime `WORKSPACE_ID`. The no-`WORKSPACE_ID` process-token fallback case is covered by regression test and fails closed before any network call. CI note: statuses for this head were still pending at review time; this approval is for the code/security review scope, not a CI override.
release-manager approved these changes 2026-05-23 08:20:07 +00:00
release-manager left a comment
Member

Approved for the scoped re-review at 218d95ace89dd3d8c274b2ba8fb41e16d78b37c7.

The per-workspace platform URL path remains resolved: molecule_runtime/executor_helpers.py:937-946 derives the pending upload workspace from the platform-pending: URI and checks the registered per-workspace platform URL before falling back to process-wide platform URLs.

The added token-isolation guard resolves the remaining process-token fallback risk: molecule_runtime/executor_helpers.py:956-967 now requires a registered token for any platform-pending: workspace that is not the single WORKSPACE_ID, including the external-runtime case where no WORKSPACE_ID is set. That prevents auth_headers(workspace_id) from falling through to MOLECULE_WORKSPACE_TOKEN / process token for a workspace that is only named in the URI.

Coverage reviewed:

  • tests/test_executor_helpers.py:1130-1192 covers per-workspace platform URL selection for tenant B while the process fallback points at tenant A.
  • tests/test_executor_helpers.py:1228-1267 covers cross-workspace pending upload rejection without a registered token.
  • tests/test_executor_helpers.py:1270-1306 covers the no-WORKSPACE_ID external-runtime case and proves the process token is not reused.

Five-axis scoped pass:

  • Correctness: no blocker; the prior routing issue and token-isolation gap are covered.
  • Readability/simplicity: no finding; the guard is localized and uses existing platform_auth APIs.
  • Architecture: no finding; it continues to use the workspace registry as the routing/auth source of truth.
  • Security: no finding; the new guard is fail-closed for cross-workspace/no-registry pending uploads.
  • Performance/release risk: no code blocker in scope. CI for this head was still queued (status=5, Waiting) during review, so merge should still wait for required checks/branch protection.

Local scoped verification on this exact head:

  • PYTHONPATH=. pytest -q tests/test_executor_helpers.py -k 'platform_pending or per_workspace_platform_url or cross_workspace_without_token or pending_without_workspace_registry or invalid_pending_upload_id' -> 7 passed, 99 deselected.
Approved for the scoped re-review at `218d95ace89dd3d8c274b2ba8fb41e16d78b37c7`. The per-workspace platform URL path remains resolved: `molecule_runtime/executor_helpers.py:937-946` derives the pending upload workspace from the `platform-pending:` URI and checks the registered per-workspace platform URL before falling back to process-wide platform URLs. The added token-isolation guard resolves the remaining process-token fallback risk: `molecule_runtime/executor_helpers.py:956-967` now requires a registered token for any `platform-pending:` workspace that is not the single `WORKSPACE_ID`, including the external-runtime case where no `WORKSPACE_ID` is set. That prevents `auth_headers(workspace_id)` from falling through to `MOLECULE_WORKSPACE_TOKEN` / process token for a workspace that is only named in the URI. Coverage reviewed: - `tests/test_executor_helpers.py:1130-1192` covers per-workspace platform URL selection for tenant B while the process fallback points at tenant A. - `tests/test_executor_helpers.py:1228-1267` covers cross-workspace pending upload rejection without a registered token. - `tests/test_executor_helpers.py:1270-1306` covers the no-`WORKSPACE_ID` external-runtime case and proves the process token is not reused. Five-axis scoped pass: - Correctness: no blocker; the prior routing issue and token-isolation gap are covered. - Readability/simplicity: no finding; the guard is localized and uses existing `platform_auth` APIs. - Architecture: no finding; it continues to use the workspace registry as the routing/auth source of truth. - Security: no finding; the new guard is fail-closed for cross-workspace/no-registry pending uploads. - Performance/release risk: no code blocker in scope. CI for this head was still queued (`status=5, Waiting`) during review, so merge should still wait for required checks/branch protection. Local scoped verification on this exact head: - `PYTHONPATH=. pytest -q tests/test_executor_helpers.py -k 'platform_pending or per_workspace_platform_url or cross_workspace_without_token or pending_without_workspace_registry or invalid_pending_upload_id'` -> `7 passed, 99 deselected`.
release-manager merged commit eb098e9585 into main 2026-05-23 08:49:41 +00:00
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-ai-workspace-runtime#45