Add reply draft creation and saved draft update/deletion operations - #57
Add reply draft creation and saved draft update/deletion operations#57jr-lillard wants to merge 13 commits into
Conversation
Spec Change ImpactModel output did not match expected format. Raw output truncated below. |
There was a problem hiding this comment.
Pull request overview
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
This PR models HEY’s browser-compatible reply-draft create/delete flows in Smithy/OpenAPI and regenerates the Go SDK so drafts can be created/discarded via form-encoded transport while preserving redirect Location headers and keeping suffixless draft routes distinct from .json send routes.
Changes:
- Add Smithy/OpenAPI support for
CreateReplyDraft(form-encoded) andDeleteDraft(POST + Rails_method=deleteoverride) and regenerate Go client types. - Update Go routing to keep
.jsonand suffixless routes distinct while providing.jsonalias matching and improved literal-vs-parameter resolution. - Introduce scoped, fail-closed route coverage generation/verification and add unit + conformance tests for draft create/delete semantics (form encoding, CSRF handling, redirect preservation).
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| spec/route-coverage.json | Adds coverage entries for reply-draft creation and draft deletion routes. |
| spec/route-coverage-scope.json | Introduces an explicit allowlist + overrides for route coverage generation. |
| spec/hey.smithy | Models CreateReplyDraft and DeleteDraft operations + supporting shapes/traits usage. |
| spec/hey-traits.smithy | Adds form-url-encoded + form-method-override Smithy traits for downstream OpenAPI tooling. |
| spec/excluded-routes.json | Removes the /messages/{id} DELETE exclusion now that it’s modeled for draft deletion. |
| scripts/generate-url-routes | Preserves .json in generated patterns so .json vs suffixless routes remain distinguishable. |
| scripts/generate-route-coverage | Generates route coverage from OpenAPI with scoped allowlist, overrides, and strict validation. |
| scripts/enhance-openapi-go-types.sh | Converts scoped form operations to application/x-www-form-urlencoded and propagates sensitivity markers. |
| scripts/check-service-drift.sh | Improves normalization so drift checks handle WithFormdataBody* generated variants. |
| openapi.json | Adds the two operations, form requestBodies, and related schemas/metadata extensions. |
| Makefile | Adds route-coverage and route-coverage-check; wires freshness check into check-mvp. |
| go/templates/imports.tmpl | Adds sort import needed for new form-normalization helper. |
| go/templates/client.tmpl | Adds redirect-capturing doer for form requests + Rails array form-key normalization during form marshaling. |
| go/pkg/hey/url.go | Updates router matching to consider .json vs suffixless routes and prefer literal routes over param routes, with alias support. |
| go/pkg/hey/url-routes.json | Regenerates the embedded route table preserving .json patterns and adding new operations. |
| go/pkg/hey/url_test.go | Adds routing tests ensuring .json send routes remain distinct and aliases resolve correctly. |
| go/pkg/hey/services_test.go | Updates addressed-field expectations and adds unit tests for create/delete draft services + Location parsing. |
| go/pkg/hey/messages.go | Fixes addressed fields to be comma-separated strings in JSON payloads. |
| go/pkg/hey/entries.go | Routes CreateReply through generated transport; adds CreateReplyDraft and DeleteDraft service methods. |
| go/pkg/hey/client.go | Wraps generated client HTTP transport to avoid following redirects for form requests (preserving Location). |
| go/pkg/generated/client.gen.go | Regenerates Go client with new operations, form bodies, metadata, and helper logic. |
| conformance/tests/reply-drafts.json | Adds conformance coverage for reply draft creation (form encoding + headers + Location). |
| conformance/tests/draft-deletion.json | Adds conformance coverage for draft deletion (method override + CSRF header + redirect preservation). |
| conformance/runner/go/main.go | Records request bodies and adds assertions for request headers/forms and response headers; wires new operations into executor. |
| behavior-model.json | Adds behavior metadata entries for CreateReplyDraft and DeleteDraft. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
All reported issues were addressed across 25 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 8 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Imported from basecamp#31 as an isolated prerequisite so this commit can be skipped when rebasing after that pull request lands.
Add Smithy form traits and generated transport for saving and deleting reply drafts. Keep suffixless draft routes distinct from JSON send routes and make the explicit route-coverage scope fail closed.
Expose SDK-backed create and delete draft workflows, preserve redirect Locations, route immediate replies through generated JSON transport, and cover the browser form contracts in unit and conformance tests.
66c3588 to
2d13b77
Compare
|
@basecamp/cli @jeremy — this is ready for maintainer review at 2d13b77. It is rebased onto current main and make check passes, including all 84 conformance cases. I also completed a controlled live create → edit → independently verify → delete smoke test against a temporary saved reply draft; no message was sent and the temporary draft was removed. The fork-origin Test and Security workflows have remained at action required, so could a maintainer approve those runs when convenient? This PR includes the addressed-fields fix from #31 as its original isolated commit with authorship preserved. Would you prefer #31 merged first, or should I keep that prerequisite in this PR? I can split the feature into smaller review units if that would materially help, but have left the current mergeable, tested stack intact to avoid churn. |
Summary
CreateReplyDraft,UpdateDraft, andDeleteDraftoperations in Smithy and regenerate the Go SDK/messages/{id}[/edit]and legacy/entries/drafts/{id}[/edit]Location families while rejecting unrelated numeric routes and unexpected suffixesRelationship to #31
This branch includes the exact patch from #31 as its first isolated commit because reply-draft handling depends on the corrected comma-separated
addressedfields. That commit preserves authorship by @cpinto and is included only as a prerequisite; #31 should still be reviewed and merged independently. If #31 lands first, this branch can be rebased and the duplicate commit dropped.Test plan
mainmake check