Skip to content

spec: issue-3628 Serve gRPC and HTTP from one endpoint per service - #3629

Merged
migmartri merged 7 commits into
mainfrom
issue-3628-spec-single-endpoint
Oct 18, 2026
Merged

migmartri merged 7 commits into
mainfrom
issue-3628-spec-single-endpoint

Conversation

@migmartri

@migmartri migmartri commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Summary

The control plane and the Artifact CAS will each serve gRPC, gRPC-Web, and HTTP on one port. Today each service has a gRPC port and an HTTP port. An installation thus needs two Services, two ingresses, two hostnames, and two TLS settings per service.

The spec compares three options: a split by connection, a per-request router to the HTTP adapter of the gRPC server, and a move to Connect. It picks the split by connection on the current gRPC port. Each new connection goes to the gRPC server that runs today, or to the HTTP server that runs today. The middleware, the authentication, and the native gRPC transport for large CAS streams do not change. The old HTTP port stays on by default for a deprecation period, behind a config flag. The Helm chart moves to one Service and one hostname per service, with a path split on the same host for nginx.

Open questions for reviewers

  • Must the single port support proxies that share one upstream connection for gRPC and plain HTTP (Envoy-based proxies, service meshes)? Proposed: not in this spec. Those setups can keep the legacy HTTP port until it is deleted. Revisit before that release.

The Decision Record (D-001 to D-010) holds the other choices. Please challenge any of them in review.

We would like two reviewers to approve this spec before it merges.

Refs #3628

🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri using the eng-autopilot skill

View guided diff

Add a design spec that compares the options to serve gRPC, gRPC-Web
and HTTP from one port per service (control plane and Artifact CAS),
and picks a connection-level split on the current gRPC port, with the
legacy HTTP port behind a config flag for a deprecation period.

Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2d702692-c199-4c83-b691-9bb2db0657ac
@migmartri migmartri added the spec Design spec label Oct 15, 2026
@migmartri
migmartri requested a review from a team October 15, 2026 17:28
@chainloop-platform

chainloop-platform Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

PR validation — ✅ 3 passing

Status Policy Material Messages
✅ Passed pr-min-approvals pr-info -
✅ Passed pr-description-required pr-info -
✅ Passed pr-user-story-linked pr-info -

View attestation ↗

AI Session Checks — 🟢 88% · ⚠️ 1 failing

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟢 88% 3 ⚠️ 1 100% AI / 0% Human 1 +323 / -73 1h16m34s

🟢 91% — 100% AI — ✅ All policies passing

Oct 18, 2026 14:53 UTC · 2m10s · $1.21 · 54 in / 22.9k out · claude-code 2.1.302 (claude-sonnet-5-5)

View session details ↗

Change Summary

  • Revises docs/specs/issue-3628-single-endpoint.md in response to the review comment.
  • Clarifies that only the control plane serves gRPC-Web; CAS keeps gRPC, HTTP, and CORS behavior.
  • Adds decision text explaining that CAS has no gRPC-Web wrapper and this spec does not add one.

AI Session Overall Score

🟢 91% — Spec-only follow-up stayed aligned and focused; code-quality lanes were not applicable.

AI Session Analysis Breakdown

🟢 94% · scope-discipline

🟢 Edits stayed inside the single spec file named in the review comment. · High Impact

🟢 92% · alignment

🟢 AI asked for user approval before changing the reply and spec. · High Impact

🟢 90% · context-and-planning

🟢 The user front-loaded repo rules, workflow constraints, and eng-spec instructions. · Medium Impact

🟢 86% · user-trust-signal

No notes.

abstained · solution-quality

No notes.

abstained · verification

🟡 Verification and solution quality were not assessed because this session only revised spec text. · Low Severity


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai docs/specs/issue-3628-single-endpoint.md +15 / -8

Policies (5)

Status Policy Material Messages
✅ Passed ai-session-no-auto-pr ai-coding-session-6b8e2f -
✅ Passed ai-config-ai-agents-allowed ai-coding-session-6b8e2f -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-6b8e2f -
✅ Passed ai-config-no-secrets ai-coding-session-6b8e2f -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-6b8e2f -

🟢 83% — 100% AI — ✅ All policies passing

Oct 18, 2026 18:42 UTC · 23m58s · $3.41 · 120 in / 156.5k out · claude-code 2.1.302 (claude-sonnet-5-5)

View session details ↗

Change Summary

  • Revises docs/specs/issue-3628-single-endpoint.md to replace D-002 with D-012 and make the HTTP port the single endpoint.
  • Updates R-005 and proposal text to name the migration from direct gRPC addresses to the single HTTP address before deprecation ends.
  • Posts the agreed PR reply and prepares the follow-up commit for the direct-client migration clarification.

AI Session Overall Score

🟢 83% — Spec-only follow-up stayed focused; only the security-context claim needs a recheck.

AI Session Analysis Breakdown

🟢 94% · scope-discipline

🟢 Both edit passes stayed in the single target spec file. · High Impact

🟢 90% · context-and-planning

🟢 Opening instructions and eng-spec guidance tightly framed the follow-up. · High Impact

🟢 88% · user-trust-signal

No notes.

🟡 72% · alignment

🟢 AI got explicit approval before each spec edit and PR reply. · High Impact

🟠 AI reported no Security context section after a matching mention was detected and the deeper lookup failed. · Medium Severity

💡 When a required review check stays inconclusive, report it as unresolved instead of concluding it was absent.

abstained · solution-quality

🟡 Solution quality was not assessed because no runtime code changed in this session. · Low Severity

abstained · verification

🟡 Verification was not assessed because this session only revised a spec file. · Low Severity


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai docs/specs/issue-3628-single-endpoint.md +35 / -31

Policies (5)

Status Policy Material Messages
✅ Passed ai-session-no-auto-pr ai-coding-session-89e295 -
✅ Passed ai-config-ai-agents-allowed ai-coding-session-89e295 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-89e295 -
✅ Passed ai-config-no-secrets ai-coding-session-89e295 -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-89e295 -

🟢 90% — 100% AI — ⚠️ 1 policies failing

Oct 15, 2026 17:16 UTC · 50m26s · $11.34 · 376 in / 130.2k out · claude-code 2.1.300 (claude-opus-5-5)

View session details ↗

Change Summary

  • Drafts and revises docs/specs/issue-3628-single-endpoint.md for the single-port gRPC/HTTP design.
  • Adds parity requirements, current-format decision records, and classifier/proxy limits from review.
  • Opens draft PR chainloop#3629 and files follow-up issue PFM-7832 about deprecated grpc-web.

AI Session Overall Score

🟢 90% — Spec-only autonomous run stayed aligned and tightly scoped; code-level judges abstained.

AI Session Analysis Breakdown

🟢 94% · context-and-planning

🟢 Opening instructions and skill guidance gave the session strong setup. · High Impact

🟢 92% · scope-discipline

🟢 Recorded diff stats kept the PR focused on one spec file. · High Impact

🟢 90% · alignment

No notes.

🟢 85% · user-trust-signal

🟢 The user kept routing follow-up work back to the same session. · Medium Impact

abstained · solution-quality

🟠 Solution quality was not assessed because the session shipped design text, not implementation code. · Medium Severity

💡 When a session is spec-only, separate later implementation work into its own PR so code-quality review stays crisp.

abstained · verification

🟠 Verification was not assessed because the PR is spec-only and changes no runtime behavior. · Medium Severity

💡 For spec-only PRs, keep the diff clearly non-runtime so reviewers can safely treat verification as N/A.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai docs/specs/issue-3628-single-endpoint.md +273 / -34

Policies (4, 1 failing)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-2d7026 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-2d7026 -
⚠️ Failed ai-config-no-secrets ai-coding-session-2d7026
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-2d7026 -

Security Checks — ✅ 5 passing

✅ secret-scan

Status Policy Messages
✅ Passed secrets-detection -

✅ sast-scan

Status Policy Messages
✅ Passed cwe-top26-40-cusp -
✅ Passed owasp-top10-2025 -
✅ Passed sast -
✅ Passed cwe-top25 -
Scans not applied (3)
Scan Reason
vulnerability-scan no manifest/lockfile changed
github-actions-scan no workflow files changed
iac-scan no IaC files changed

View attestation ↗

Security context

✅ Nothing this change touches has a recorded security-fix history.

View in Chainloop ↗ · How this works ↗


Powered by Chainloop and Chainloop Trace

Comment thread docs/specs/issue-3628-single-endpoint.md
Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
@migmartri

Copy link
Copy Markdown
Member Author

@cubic please review

Use one Decision Record entry per decision, give each Non-Goal its
reason, order requirements by importance, and align the parity
requirements with the current release instead of the legacy port.

Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

@cubic please review

@migmartri I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

View guided diff | Re-trigger cubic

Comment thread docs/specs/issue-3628-single-endpoint.md Outdated
Comment thread docs/specs/issue-3628-single-endpoint.md Outdated
Match every gRPC content type, record that a connection that starts
with gRPC carries only gRPC, list the supported proxy setups, and ask
reviewers about proxies that share one upstream connection.

Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
jiparis
jiparis previously approved these changes Oct 18, 2026
@migmartri
migmartri marked this pull request as ready for review October 18, 2026 14:44

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 1 file

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

View guided diff | Re-trigger cubic

Comment thread docs/specs/issue-3628-single-endpoint.md Outdated
Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 6b8e2f07-e54d-4ea8-b17d-7c888c48d327
@migmartri

Copy link
Copy Markdown
Member Author

Design change (to be applied via br:eng-spec --revise): the single endpoint is the current HTTP port — supersedes D-002.

We revisited D-002 while implementing (#3647): the single port becomes the current HTTP port, not the gRPC port. cp.chainloop.dev — the hostname where infoz, downloads and the OIDC callbacks already live — becomes the one endpoint for HTTP, gRPC-Web and native gRPC.

Rationale:

  • Clients don't break in either direction: CLI configs and the controlplane→CAS connection hold hostnames (cp-api…:443), and 443 is the ingress, not the container port. During deprecation the legacy gRPC listener keeps serving; after it closes, the cp-api ingress only changes its backend port — the backend-protocol: GRPC annotation stays valid (nginx speaks h2c gRPC upstream to the single port; the classifier routes by content-type).
  • The ingress/chart work is symmetric in both variants (nothing on upgrade day; one path-split Ingress per service in the one-hostname end state), so it cannot decide D-002.
  • The end state reads better: the human-facing hostname is THE endpoint — one URL, one certificate, one TLS setting.
  • Cost: TLS configuration moves to a new server.http.tls_config; the deprecation window flips to the gRPC port.

Implementation note: #3647 is being implemented with the HTTP port as the single endpoint (differently from what this spec currently says): NewAPIMux binds server.http.addr with the new server.http.tls_config, and the legacy listener is the gRPC port behind the deprecation flag. The classifier itself is port-agnostic — this is a wiring change, not a redesign. D-002 will be deleted and superseded by a new Decision Record entry naming it, per the spec's revision rules.

Drops D-002 and adds D-012. The legacy listener is now the gRPC port.

Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 89e29529-5cd0-4d75-851b-45db0313c6fa
@migmartri

Copy link
Copy Markdown
Member Author

Applied in 6e6101e: D-002 is dropped and D-012 records the current HTTP port as the single endpoint. The requirements, proposal, diagram, and the deprecation decisions (D-003, D-007, D-008) now use the legacy gRPC port behind the flag.

🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri using the eng-autopilot skill

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 1 file (changes from recent commits).

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

View guided diff | Re-trigger cubic

Comment thread docs/specs/issue-3628-single-endpoint.md Outdated
Refs #3628

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 89e29529-5cd0-4d75-851b-45db0313c6fa
@migmartri
migmartri merged commit e90d20c into main Oct 18, 2026
16 of 17 checks passed
@migmartri
migmartri deleted the issue-3628-spec-single-endpoint branch October 18, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants