Skip to content

feat(campfires): add UpdateCampfireLine operation#295

Merged
jeremy merged 7 commits into
basecamp:mainfrom
nnemirovsky:feat/campfires-update-line
Jul 22, 2026
Merged

feat(campfires): add UpdateCampfireLine operation#295
jeremy merged 7 commits into
basecamp:mainfrom
nnemirovsky:feat/campfires-update-line

Conversation

@nnemirovsky

@nnemirovsky nnemirovsky commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds UpdateCampfireLine (PUT /{accountId}/chats/{campfireId}/lines/{lineId}) so callers can edit existing campfire messages instead of delete-and-repost. The endpoint is accepted by the Basecamp API but was not previously surfaced in the spec.

Verified live against a real Basecamp account: PUT returns 204 and the line content updates as expected.

Changes

  • spec/basecamp.smithy + spec/overlays/tags.smithy: new operation, tagged Campfire, registered in service operations
  • openapi.json regenerated via make smithy-build
  • All 6 SDKs regenerated (Go, TypeScript, Ruby, Python, Swift, Kotlin) — make ts-generate ts-generate-services rb-generate rb-generate-services py-generate swift-generate kt-generate-services
  • Service generator configs updated in 5 places to map UpdateCampfireLine → updateLine / update_line:
    • typescript/scripts/generate-services.ts
    • ruby/scripts/generate-services.rb
    • python/scripts/generate_services.py
    • kotlin/generator/.../Config.kt
    • swift/Sources/BasecampGenerator/{MethodNaming,ServiceGrouper}.swift
  • go/pkg/basecamp/campfires.go: hand-written CampfiresService.UpdateLine(ctx, campfireID, lineID, content, *UpdateLineOptions). The API returns 204; the wrapper returns only an error (mirrors DeleteLine) so a transient post-mutation read can not make a successful update appear to fail. Callers that need the canonical post-update line follow up with GetLine.
  • Tests: 4 Go (go/pkg/basecamp/campfires_test.go), 2 Ruby (ruby/test/.../campfires_service_test.rb), 2 TypeScript (typescript/tests/services/campfires.test.ts)
  • typescript/README.md, go/README.md, AGENTS.md operation count refreshed (175 → 204)

Test plan

  • make go-check — Go tests + lint pass
  • make ts-check — 618 tests pass
  • make rb-check — 601 tests pass
  • make py-check — 209 tests pass
  • make swift-check — 166 tests pass
  • make kt-check — Kotlin build + tests pass
  • make go-check-drift / make py-check-drift / make kt-check-drift — no drift
  • make conformance — 64 passed, 0 failed
  • Live PUT against a real campfire line — 204, content updated, restored cleanly

Related

CLI consumer that exercises this op: basecamp/basecamp-cli#462


Maintainer update (jeremy, 2026-07-22)

The description above reflects the original submission; the branch has since been completed to house standard (details in this comment). Contract-relevant deltas:

  • content_type was dropped from the update operation — the server ignores it and coerces every edited line to rich text (HTML). The Go wrapper is now UpdateLine(ctx, campfireID, lineID, content) error with no options struct.
  • Rebased onto current main; bc3 provenance pin advanced after a full drift audit (API version 2026-07-21).
  • Test coverage backfilled across all six SDKs: 204 happy path + 422 validation mapping, body asserted to carry only content; campfire line ops added to Python (sync + async), Kotlin, and Swift suites.
  • SPEC.md operation counts refreshed (181 → 204).

Summary by cubic

Adds UpdateCampfireLine so clients can edit Campfire messages via PUT /{accountId}/chats/{campfireId}/lines/{lineId}. Updates are always rich text, and only the line’s creator can edit text/rich‑text lines.

  • New Features
    • Spec/OpenAPI: new PUT; idempotent with 3 retries; API version 2026-07-21; tags/behavior model updated; total operations now 204. Delete docs now state creator‑or‑admin with 403 otherwise.
    • Request body: content required; content_type removed; docs note rich‑text coercion and creator‑only edits.
    • SDKs: regenerated for Go, TypeScript, Ruby, Python (sync+async), Swift, Kotlin; method maps to updateLine/update_line. Go UpdateLine(ctx, campfireID, lineID, content) -> error; TypeScript updateLine(...) -> void; both reject empty content; others return void/Unit.
    • Tests: added across all six SDKs for 204 happy path and 422 validation; assert body carries only content. Live PUT verified (204).

Written for commit 4de7624. Summary will update on new commits.

Review in cubic

@github-actions github-actions Bot added documentation Improvements or additions to documentation typescript Pull requests that update TypeScript code ruby Pull requests that update the Ruby SDK go kotlin swift spec Changes to the Smithy spec or OpenAPI labels May 4, 2026
@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown

Spec Change Impact

  • Added:

    • UpdateCampfireLine operation.
  • SDKs needing regeneration: All SDKs must be regenerated due to the added operation.

  • Breaking change: No, this is not a breaking API change.

  • Checklist of SDKs needing updates:

    • Go
    • TypeScript
    • Ruby
    • Kotlin
    • Swift

@github-actions github-actions Bot added enhancement New feature or request and removed documentation Improvements or additions to documentation labels May 4, 2026
@nnemirovsky
nnemirovsky marked this pull request as ready for review May 4, 2026 10:34
Copilot AI review requested due to automatic review settings May 4, 2026 10:34

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

No issues found across 35 files

Copilot AI 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.

Pull request overview

Adds a new Campfires operation, UpdateCampfireLine (PUT /{accountId}/chats/{campfireId}/lines/{lineId}), to let SDK consumers edit existing campfire lines without delete-and-repost. This change updates the Smithy source of truth, regenerates the OpenAPI + all SDKs, and adds language-specific naming/config glue plus tests.

Changes:

  • Extend the Smithy spec (and tags overlay) with UpdateCampfireLine, including idempotency + retry metadata, and regenerate openapi.json / derived artifacts.
  • Regenerate TypeScript/Ruby/Python/Swift/Kotlin SDKs to expose updateLine / update_line methods and update service-generator configs to map the new operation name correctly.
  • Add a hand-written Go CampfiresService.UpdateLine(...) wrapper (re-fetching the updated line after a 204) and add new tests (Go/TS/Ruby).

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.

Reviewed changes

Copilot reviewed 17 out of 35 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
typescript/tests/services/campfires.test.ts Adds MSW-backed tests for campfires.updateLine (204 + validation).
typescript/src/generated/services/campfires.ts Adds generated updateLine method + request interface.
typescript/src/generated/schema.d.ts Updates OpenAPI-derived TS types to include PUT for campfire lines.
typescript/src/generated/path-mapping.ts Registers PUT campfire-line route → UpdateCampfireLine.
typescript/src/generated/openapi-stripped.json Updates stripped OpenAPI with new PUT operation + schema.
typescript/src/generated/metadata.json Adds retry/idempotency metadata entry for UpdateCampfireLine.
typescript/scripts/generate-services.ts Updates service splits + method name override to include UpdateCampfireLine → updateLine.
typescript/README.md Documents the new campfires.updateLine method in the service list.
swift/Sources/BasecampGenerator/ServiceGrouper.swift Adds UpdateCampfireLine to Campfires grouping for generation.
swift/Sources/BasecampGenerator/MethodNaming.swift Adds method name override UpdateCampfireLine → updateLine.
swift/Sources/Basecamp/Generated/Services/CampfiresService.swift Adds generated updateLine(...) API in Swift service.
swift/Sources/Basecamp/Generated/Models/UpdateCampfireLineRequest.swift Adds generated request model for update line.
swift/Sources/Basecamp/Generated/Metadata.swift Adds retry config entry for UpdateCampfireLine.
spec/overlays/tags.smithy Tags UpdateCampfireLine as Campfire.
spec/basecamp.smithy Defines UpdateCampfireLine operation + input/output in Smithy.
ruby/test/basecamp/services/campfires_service_test.rb Adds Ruby tests for update_line (with/without content_type).
ruby/scripts/generate-services.rb Adds operation to Campfires service split + method name override.
ruby/lib/basecamp/generated/types.rb Refreshes generation timestamp header.
ruby/lib/basecamp/generated/services/campfires_service.rb Adds generated update_line(...) method implementation.
ruby/lib/basecamp/generated/metadata.json Adds retry/idempotency metadata entry for UpdateCampfireLine.
python/src/basecamp/generated/types.py Adds TypedDict for UpdateCampfireLineRequestContent.
python/src/basecamp/generated/services/campfires.py Adds sync/async update_line(...) methods.
python/src/basecamp/generated/metadata.json Adds operation metadata entry for retry/idempotency.
python/scripts/generate_services.py Adds operation to Campfires service list + name override.
openapi.json Adds PUT operation + request schema for UpdateCampfireLine.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/services/Types.kt Adds UpdateCampfireLineBody model.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/services/campfires.kt Adds generated updateLine(...) method.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/Metadata.kt Adds retry metadata for UpdateCampfireLine.
kotlin/generator/src/main/kotlin/com/basecamp/sdk/generator/Config.kt Updates service split + method name override for UpdateCampfireLine.
go/README.md Documents Campfires().UpdateLine in the Go service list.
go/pkg/generated/client.gen.go Regenerates Go client with UpdateCampfireLine request/response plumbing.
go/pkg/basecamp/campfires.go Adds hand-written CampfiresService.UpdateLine(...) wrapper + options.
go/pkg/basecamp/campfires_test.go Adds Go tests covering UpdateLine validation + request shape + refetch.
behavior-model.json Adds retry/idempotency behavior model entry for UpdateCampfireLine.
AGENTS.md Updates operation count and generated-operations description.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/pkg/basecamp/campfires.go Outdated
@nnemirovsky
nnemirovsky force-pushed the feat/campfires-update-line branch from f58f166 to 75f73ca Compare May 4, 2026 10:44
@github-actions github-actions Bot added documentation Improvements or additions to documentation and removed documentation Improvements or additions to documentation labels May 4, 2026
nnemirovsky added a commit to nnemirovsky/basecamp-cli that referenced this pull request May 4, 2026
Addresses Copilot review on basecamp/basecamp-sdk#295: align UpdateLineOptions
ContentType doc with the rest of the campfires service (API defaults to plain
text).
@nnemirovsky
nnemirovsky requested a review from Copilot May 4, 2026 10:50

Copilot AI 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.

Pull request overview

Copilot reviewed 17 out of 35 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nnemirovsky
nnemirovsky force-pushed the feat/campfires-update-line branch from 75f73ca to 26d71f1 Compare May 4, 2026 11:16
@github-actions github-actions Bot added documentation Improvements or additions to documentation and removed documentation Improvements or additions to documentation labels May 4, 2026
@nnemirovsky
nnemirovsky requested a review from Copilot May 4, 2026 11:37

Copilot AI 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.

Pull request overview

Copilot reviewed 17 out of 35 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/pkg/basecamp/campfires.go Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 06:29
Adds an UpdateCampfireLine operation across all six SDKs, generated from
the Smithy spec. Maps PUT /chats/{campfireId}/lines/{lineId}, which the
Basecamp API accepts but the spec did not previously expose.

- Smithy: new operation with Campfire tag, registered in service operations
- Generated clients regenerated for Go, TypeScript, Ruby, Python, Swift, Kotlin
- Service generator mappings (TS, Ruby, Python, Swift, Kotlin) updated to
  rename UpdateCampfireLine -> updateLine / update_line
- Go service wrapper UpdateLine returns the re-fetched line (API responds 204)
- Go, Ruby, TypeScript tests cover happy path and validation
- AGENTS.md operation count refreshed (175 -> 204)

Verified: PUT /chats/{c}/lines/{l} with {content,content_type} returns 204
against a real Basecamp account; the line content updates as expected.

Copilot AI 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.

Pull request overview

Copilot reviewed 24 out of 42 changed files in this pull request and generated 4 comments.

Comment thread typescript/tests/services/campfires.test.ts
Comment thread python/tests/services/test_campfires_service.py Outdated
Comment thread python/tests/services/test_campfires_service.py Outdated
Comment thread go/pkg/basecamp/campfires_test.go Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 08:34
@jeremy
jeremy force-pushed the feat/campfires-update-line branch from 49712f5 to 3841ee1 Compare July 22, 2026 08:34
@github-actions github-actions Bot added documentation Improvements or additions to documentation and removed documentation Improvements or additions to documentation labels Jul 22, 2026
jeremy added 6 commits July 22, 2026 01:38
The server ignores content_type on line updates: Chats::LinesController#update
strips it (update_params = line_params.except(:content_type)) and coerces every
edited line to rich text via becomes(Chat::Lines::RichText). Only the line's
creator may edit, and only text/rich-text lines are editable
(Person::Ability#can_edit_chat_line?). Publicly documented in
doc/api/sections/campfires.md ("Update a Campfire line", bc3-api af143f25;
registered as the campfire-line-edit api-gap by basecamp#390).

Drop the dead content_type parameter from UpdateCampfireLineInput and
regenerate all six SDKs; document the rich-text coercion and creator-only
constraint on the operation. Simplify the Go wrapper to
UpdateLine(ctx, campfireID, lineID, content) — no options struct — matching
DeleteLine's shape. The operation is unreleased, so no compatibility concern.

Endpoint semantics were verified against bc3 through 13c84145 via a full
drift audit of e52453ff..13c84145; the provenance pin itself advanced
separately on main (basecamp#390, to ba105ba7), so this commit no longer touches it.

Test adjustments: drop the Go option-validation tests with the options struct,
assert the update body carries only content; drop the Ruby content_type
variant; add 422 mapping coverage for update_line in Ruby and TypeScript.
Backfill service tests for create_line/get_line/update_line/delete_line.
update_line gets happy-path (204 -> None, body carries only content) and
422 ValidationError cases in both the sync and async clients.
Backfill CampfiresServiceTest: createLine/getLine/deleteLine happy paths,
updateLine PUT with a content-only body, and 422 -> Validation mapping.
Backfill GeneratedServiceTests: createLine/getLine/deleteLine happy paths,
updateLine PUT with a content-only body, and 422 -> .validation mapping.
behavior-model.json now carries 204 operations (66 idempotent, 138 not);
the retry-pattern claims (three (max, base_delay_ms) shapes, all
retry_on [429, 503]) were re-verified against the model and still hold.
…ssions

Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the
UpdateCampfireLine Smithy ref, per the absorption plan basecamp#390 registered.
While absorbing, refresh DeleteCampfireLine's doc comment with the
newly documented creator-or-admin / 403 contract from the same section
of doc/api/sections/campfires.md.
@jeremy
jeremy force-pushed the feat/campfires-update-line branch from 3841ee1 to 4de7624 Compare July 22, 2026 08:38
@github-actions github-actions Bot added documentation Improvements or additions to documentation and removed documentation Improvements or additions to documentation labels Jul 22, 2026

Copilot AI 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.

Pull request overview

Copilot reviewed 24 out of 42 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 22, 2026 08:39

Copilot AI 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.

Pull request overview

Copilot reviewed 24 out of 42 changed files in this pull request and generated no new comments.

@jeremy
jeremy merged commit 09f7b32 into basecamp:main Jul 22, 2026
48 checks passed
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to nnemirovsky/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
jeremy pushed a commit to basecamp/basecamp-cli that referenced this pull request Jul 22, 2026
Adds 'basecamp chat update <id|url> [content]' for editing existing
campfire lines in place via PUT /chats/{c}/lines/{l}, backed by the
SDK's CampfiresService.UpdateLine.

Content handling has four explicit modes, validated before any request:
- default: Markdown converted to HTML unconditionally, then @mentions
  resolved (edits always render as rich text server-side);
- --content-type text/html: HTML supplied as-is, then @mentions resolved;
- --content-type text/plain: serialized verbatim via richtext.PlainToHTML
  (escaped, line breaks preserved as <br>), mention resolution skipped;
- any other value: rejected with a usage error.

--content-type is applied client-side only; the SDK PUT carries just the
content, and the server coerces every edit to rich text.

URL arguments route through the shared urlarg parser (which gains a
CampfireID field for the chat-line route) plus a hostutil trusted-host
gate, so a pasted card/todo URL, a boundary-evading line ID, or a
look-alike on an untrusted host is rejected rather than silently
misinterpreted; a URL whose account differs from the configured account
is refused. The 204 PUT is followed by a GetLine re-fetch so the response
carries the canonical post-update line.

Bumps the SDK to CampfiresService.UpdateLine (basecamp/basecamp-sdk#295,
merge commit 09f7b326), pinned to the merge commit pending a release tag.
Wires up the surface snapshot, catalog, e2e + smoke coverage, and the
basecamp skill documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request go kotlin ruby Pull requests that update the Ruby SDK spec Changes to the Smithy spec or OpenAPI swift typescript Pull requests that update TypeScript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants