Skip to content

feat(calls): read and change team call data retention - #22

Merged
purpshell merged 13 commits into
devfrom
t3code/calls-retention
Sep 23, 2026
Merged

purpshell merged 13 commits into
devfrom
t3code/calls-retention

Conversation

@purpshell

@purpshell purpshell commented Sep 19, 2026 •

Copy link
Copy Markdown
Member

polymorfa calls retention get reads the team's call-data retention setting. calls retention set changes it with a required --expected-revision, validates named and custom periods, and asks for confirmation before shortening the period. A stale revision exits 4; missing authority exits 3 with an actionable message. Team API keys can read and change the setting. Project tokens can read it without supplying a project ID; the API rejects their changes.

The CLI uses the typed @polymorfa/sdk team-wide retention client for both credentials. This replaces the temporary raw request bridge. The dependency is pinned to @polymorfa/sdk@0.1.0-dev.20260923112126, published from SDK source e38db510a12b6e1ee7c36087f6b8267038509929 (SDK dev merge 4a1c97ab5210c9726c94a4dc8288292928950759). The CLI PR targets dev.

Verification

  • npm ci --ignore-scripts and npm run verify pass against the published SDK: format, lint, typecheck, 74 test files / 648 tests, build, package dry run, and production audit with 0 vulnerabilities. The downloaded SDK tarball's SHA-512 matches the registry metadata and lockfile integrity.
  • Focused retention command and service tests: 32 passed against the local SDK pack. They cover human and JSON output, revision conflicts, shortening confirmation, 403 errors, project-token read and denied change, and malformed response envelopes.
  • No request was made against a deployed API. The command tests use a loopback HTTP server.

API, SDK, CLI, docs, feature release, Admin

  • API — unchanged here. Monorepo PR #235 merged the authoritative GET and PUT /platform/call-retention contract into dev at 109ac4c110d8aabad1f95864c29bee31960a7d11. The CLI's request bodies, team scope, and 409/403 paths match the current route.
  • SDK — updated in feat(platform): read and update team call data retention sdks#278. The typed retention resource and the team-wide project-token entrypoint were merged to SDK dev; this CLI pins their published prerelease.
  • CLI — updated here. Adds calls retention get|set, help and examples, team-setting credential resolution, confirmation and error handling, and typed SDK integration.
  • Docs — updated. CLI README and command research describe the commands; SDK README documents project-token reads. The monorepo's Mintlify retention guide and API reference were updated in #235. No public route or output shape changes in this adapter update.
  • Feature release — unchanged here. Saving the setting does not start deletion. The production purge remains disabled until a separately authorized rollout and customer notice; merging this CLI does not establish deployed availability.
  • Admin — unaffected here. Admin retention controls remain in monorepo #235 through their API-owned capability; this CLI does not call the Admin path.

Add `calls retention get` and `calls retention set` for
GET/PUT /platform/call-retention. The pinned SDK has no call-retention
resource, so a CLI adapter (createCallRetentionClient) sends the requests
through the organization client's raw transport.

`set` requires --expected-revision, reads the setting first, fails with
state_conflict (exit 4) on a stale revision, and asks for confirmation
(or --yes; exit 2 confirmation_required without a terminal) before a
shorter period deletes stored call data. 403 and 409 responses get
actionable messages.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

  • Ask an admin to enable usage-based reviews

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 74 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 617cf963-dc75-4ad7-bcc6-a66d559ba20e

📥 Commits

Reviewing files that changed from the base of the PR and between d7cb76c and df89c75.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • README.md
  • docs/command-research/calls.md
  • package.json
  • src/base-command.ts
  • src/commands/calls/retention/get.ts
  • src/commands/calls/retention/set.ts
  • src/context/environment.ts
  • src/sdk/client.ts
  • src/services/calls.ts
  • test/commands/calls.test.ts
  • test/services/call-retention.test.ts

Comment @coderabbitai help to get the list of available commands.

@purpshell

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-23T12:09:15.360703Z df89c75 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 431b29fd61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/commands/calls/retention/get.ts Outdated
async run(): Promise<void> {
const {flags} = await this.parse(CallsRetentionGet)
const result = await viewCallRetention(
createCallRetentionClient(await this.platformEnvironment(flags)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept project tokens on retention reads

calls retention get always uses platformEnvironment, whose resolver rejects POLYMORFA_PROJECT_TOKEN and project-token profiles before transport. This prevents authorized project-token users from reading the setting even though the API contract documented in docs/command-research/calls.md:89-91 explicitly permits project tokens; it also means calls retention set rejects such tokens locally with exit 2 instead of reaching the documented authorization failure with exit 3. Use credential resolution and a raw client that can preserve a project-token principal for this resource.

Useful? React with 👍 / 👎.

…nablement truthfully

calls retention get resolved Platform credentials, which accept only team
API keys, so project tokens were refused locally although the API lets them
read the team setting; calls retention set likewise refused them with exit 2
instead of reaching the API's 403 (exit 3).

Both commands now resolve a team API key or a project token, from the
environment or a profile, with no project context, and the API decides.
Team keys keep the SDK raw transport. The pinned SDK confines project-token
raw requests to /platform/projects/{id} and refuses a project token as an
organization key, so project tokens use a narrow single-request transport
that sends the SDK's headers, refuses non-loopback http and redirects, and
maps failures to the SDK error classes. Remove it once a pinned SDK release
serves this route (polymorfa/sdks#278).

Help text and README now say deletion starts on a date Polymorfa announces,
matching the API: the production purge is not enabled yet.
@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44ddc255a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/commands/calls/retention/set.ts Outdated
} from '../../../services/calls.js'

export default class CallsRetentionSet extends BaseCommand {
static override description = `Change how long Polymorfa keeps your team’s call data through the Platform API. --policy short, standard, extended, or compliance keeps call data for 7, 30, 90, or 365 days; --policy custom keeps it for --days (${MIN_CALL_RETENTION_DAYS} to ${MAX_CALL_RETENTION_DAYS}). Deletion of call data older than the period starts on a date Polymorfa announces in its changelog; until then saving a period deletes nothing. Once deletion runs, a shorter period also applies to call data already stored, and deleted call data cannot be recovered, so the command asks you to confirm a shorter period; pass --yes to confirm without a prompt (required when standard input or error is not a terminal). --expected-revision is required: the command reads the setting first and changes it only if it still has that revision (see \`calls retention get\`); otherwise it fails with state_conflict (exit code 4) and changes nothing. Requires a team API key with the sessions:manage scope; the API refuses project tokens (exit code 3).`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the read scope required by retention set

For a team key that has sessions:manage but not sessions:read, this help text claims the credential is sufficient, but updateCallRetention always performs client.retrieve() before attempting the PUT, and the read endpoint requires sessions:read. Such users therefore receive a 403 and can never make the otherwise-authorized change; either allow manage-only credentials through the preliminary read or state that this command requires both scopes.

Useful? React with 👍 / 👎.

…:manage

calls retention set reads the setting before it changes it, and the API does
not let sessions:manage imply sessions:read. The help text, README and command
research now name both scopes, and a 403 on the preliminary read gets the
change message instead of the read-only one.
# Conflicts:
#	docs/command-research/calls.md
@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a98c4a4174

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/command-research/calls.md Outdated
Comment on lines +101 to +105
pinned SDK has no call-retention resource. `createCallRetentionClient` in
`src/sdk/client.ts` sends `GET` and `PUT /platform/call-retention` through
the SDK organization client's raw transport for team API keys. The pinned
SDK confines a project-token client's raw paths to `/platform/projects/{id}`
and refuses a project token as an organization key, so project tokens use

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Describe the typed retention client

This section describes an implementation that is absent from the final tree: createCallRetentionClient in src/sdk/client.ts now calls the pinned SDK's createTeamCallRetentionClient for both credential types, while src/sdk/project-token-request.ts no longer exists. Leaving the research guide saying the SDK lacks this resource and recommending a future migration can mislead subsequent maintenance; update this section and the operation table to reflect the typed SDK integration.

Useful? React with 👍 / 👎.

@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 9cf78c8036

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# Conflicts:
#	package-lock.json
#	package.json
@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@purpshell

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: f5478cb5b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df89c75c01

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/services/calls.ts
typeof current.retentionDays !== 'number' ||
retentionDays < current.retentionDays
) {
await confirmShorter(current, retentionDays)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve project-token authorization on shorter changes

When a project token requests a shorter period (for example, --policy short from the 90-day default), updateCallRetention invokes confirmation before sending the PUT; therefore a noninteractive call without --yes exits 2 with confirmation_required, and an interactive user is prompted to approve a change they cannot make, instead of receiving the documented API refusal with exit 3. Although the new credential resolver fixes the previous blanket project-token rejection, this shorter-policy path is fresh evidence that some project-token changes still do not reach the API as promised.

Useful? React with 👍 / 👎.

@purpshell

Copy link
Copy Markdown
Member Author

Merge gate for df89c75c0191806baa02a68dfdae38c077b5ab80 against dev (d7cb76c62aa627cbcc4df35ddfb7f1cc61506170): Node 22 CI run 35858292207 passed. A local codex review --base origin/dev on this exact clean head found no actionable regressions; the previous GitHub Codex review of the merge head was also clean, and its one earlier retention-error diagnostic finding is fixed with a passing regression on this head. CodeRabbit reports Review rate limited, so no clean CodeRabbit review is claimed. The owner explicitly authorized merging CLI #22 with current-head CI and Codex in place of the handoff's CodeRabbit gate. This merge does not deploy or release Calls.

@purpshell
purpshell merged commit 7fc6e95 into dev Sep 23, 2026
3 checks passed
@purpshell
purpshell deleted the t3code/calls-retention branch October 26, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant