Skip to content

feat:Brevo function - #100

Merged
piyushsarin-sib merged 54 commits into
mainfrom
features_set-dp-function
Sep 4, 2026
Merged

feat:Brevo function#100
piyushsarin-sib merged 54 commits into
mainfrom
features_set-dp-function

Conversation

@satyamdev10

@satyamdev10 satyamdev10 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Add the full brevo function (alias brevo fn) command surface for creating, managing, and deploying Brevo Functions from the CLI.

New commands

  • brevo function list — List all Brevo Functions on the account (supports --json, --drafts)
  • brevo function get — Show details of a single function by --id or interactive selection
  • brevo function activate — Activate a function
  • brevo function deactivate — Deactivate a function
  • brevo function delete — Delete a function (with confirmation prompt, --force to skip)
  • brevo fn init — Interactive AI-powered function creation: describe intent, pick a template or generate from scratch, preview with sample contacts, iterate, and deploy
  • brevo fn deploy — Deploy a draft function to production and optionally link it to an app

Key implementation details

  • All commands support --json for scripted/CI usage and --id for non-interactive targeting
  • Shared helpers in function-action.ts (resolveFunctionId, withNotFoundHandling, executeFunctionAction, buildFunctionActionCommand) eliminate duplication across action commands
  • select-function.ts provides reusable interactive function picker with assertFunctionSelectionAllowed guard for non-TTY contexts
  • deploy-helpers.ts extracts shared deploy logic (app selection, linking) to reduce cognitive complexity
  • preview-table.ts renders function preview results as formatted tables
  • SSE streaming support added to api/sse-stream.ts for real-time AI generation feedback during fn init
  • 403 handling shows a friendly "Functions not enabled" message when the account lacks the feature
  • GA release: preview gate removed — all function commands ship in the published build

Smoke tests

  • Full function suite added to the smoke test runner covering: list, get, activate/deactivate cycle, deploy, init (with PTY interaction), and cleanup
  • Suite registered in smoke.yml for CI (pre-merge, post-merge, and manual dispatch)

Other changes

  • New user-facing strings in src/lang/en.ts for all function commands
  • CLI constants added to src/lib/constants.ts
  • FEATURE_STAGE['function'] set to 'ga' in src/lib/preview.ts
  • functionService added to src/container.ts and src/services/function.ts
  • App config template updated to include function-related fields

Test plan

satyamdev10 and others added 30 commits August 14, 2026 15:04
Add `brevo function list` and `brevo function get <id>` commands for
managing Brevo Functions, plus the "Brevo Function" app type choice
in `brevo app create`.

- New service (src/services/function.ts) with list, draft list, and get
- New command handlers (src/commands/function/list.ts, get.ts)
- Register functionCommandGroup in definitions.ts and bin/index.ts
- Add Function commands section to root help screen
- Add brevo_function template flag for app-config.json rendering
- Add Brevo Function app type to interactive create prompt (private only)
- Unit tests for service, list command, and get command (23 tests)
- Command registration tests in definitions.test.ts (4 tests)
- Help formatting tests updated for functionCommandGroup
- New smoke suite (scripts/smoke/function.ts) exercising list, list
  --draft, get, and get-not-found against a real account — opt-in via
  `yarn smoke --suite=function`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `brevo-function-type` to FEATURE_STAGE as a preview feature
- Move function group definition to preview-definitions.ts so esbuild
  can eliminate it from published builds
- Gate the Brevo Function choice in `app create` behind __BREVO_PREVIEW__
- Gate the Function commands section in help.ts behind __BREVO_PREVIEW__
- Add `aliases` support to SubcommandGroupDefinition so `brevo fn list`
  and `brevo fn get` work as shortcuts
- Update tests for the conditional export and gated app-type prompt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add three management commands to the Brevo Function group:
- `brevo function activate <id>` — PATCH with is_active: true
- `brevo function deactivate <id>` — PATCH with is_active: false
- `brevo function delete <id>` — DELETE with --force to skip confirmation

All three are gated behind __BREVO_PREVIEW__ alongside the existing
list and get commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add brevo function activate, deactivate and delete commands
…d SSE error handling

- Add `brevo fn init` command with two creation flows: AI generation and global templates
- Implement SSE streaming for AI code generation and iteration with colored progress stages
- Add preview execution (fetch contacts + execute + results table) after generation and iteration
- Auto-derive `attribute_id` from function name in SCREAMING_SNAKE_CASE
- Add graceful error handling for SSE stream termination and API failures
- Add shared function app selector (`select-function.ts`) used by fn subcommands
- Update all fn subcommands to use shared app selector
- Set `source: 'cli'` on all dp-functions API calls
- Wrap SSE reader.read() errors into ApiError for clean failure messages
- Add comprehensive tests for init command and SSE stream module

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backend updates the draft in the database during iterate (PATCH
/generate/stream) in all auth modes, so referencing the draft by ID
is consistent with the initial preview and avoids sending the full
code payload to the execute endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dp-functions backend returns 403 with code `feature_not_enabled`
when the account lacks the dp-functions entitlement. Map this to a
user-friendly message in both the REST client (ApiClient) and the
SSE stream handler so all fn subcommands display:

  "Brevo Functions is not enabled for this account."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ernaries

- sse-stream.ts: extract performSSEFetch, handleSSEErrorResponse, readChunk,
  processSSELine, flushSSEState helpers to reduce cognitive complexity from 49
  to ~11; replace nested ternary with extractErrorMessage function
- init.ts: extract executePreview, saveGeneratedFunction, mergeGenerateResult,
  updateSpinnerFromEvent, accumulateResult helpers to reduce cognitive complexity
  of processGenerateStream (38→~8) and aiGenerationFlow (40→~11); combine
  consecutive push calls into single push with multiple args
- list.ts: extract inner template literals to variables to eliminate nesting
- templates/index.ts: replace nested ternary with if/else in resolveTemplateFlags
- create.ts: replace nested ternary with if/else in buildCreatePayload; extract
  cacheCreatedAppCredentials to reduce createCommand complexity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Parameterize similar tests in sse-stream.test.ts and definitions.test.ts (S5976)
- Add formatCellValue helper for safe object stringification in init.ts (S6551)
- Replace boolean statusBadge function with ACTIVE_BADGE/INACTIVE_BADGE constants in list.ts (S2301)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use explicit type checks (string, number, boolean) instead of
String(value) on unknown, so SonarCloud can verify no object
reaches the default toString path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Attribute ID was shown both as a header line and could appear in the
results table. Remove the explicit header line so the preview only shows
the description and the data table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use shared functionService from container instead of local instance (init.ts)
- Wire STAGE_LABELS to lang file keys instead of hardcoded strings
- Rethrow ApiError/CliError in generate and iterate catch blocks
- Guard iterate request and preview against missing draftId
- Match duplicate-name detection on HTTP 409 status code, not message copy
- Union columns across all rows in printResultsTable
- Document AbortSignal.timeout as a deadline in sse-stream.ts
- Evaluate statusBadge at call time to respect TTY/NO_COLOR (list.ts)
- Change --id [id] to --id <id> in all fn subcommands
- Remove orphaned lang keys (stage labels, success messages, file-written)
- Hoist distribution_type out of template branches (app-config.json.tmpl)
- Remove unused src/__tests__/tsconfig.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- init.ts: extract `runIterateRound` and `tryPreview` from
  `aiGenerationFlow` to reduce cognitive complexity from 21 to
  within the 15 threshold (typescript:S3776).
- list.ts: replace `statusBadge(isActive)` boolean-param function
  with two named functions `activeBadge()` / `inactiveBadge()`
  (typescript:S2301).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…provements

feat: add brevo fn init with AI generation, templates, and error handling
Add a standalone deploy command that lets users deploy draft Brevo
Functions independently of the `brevo fn init` AI generation flow.

- New `brevo function deploy` command with `--id` and `--json` flags
- Interactive draft picker when `--id` is omitted
- Preview with sample contacts before deployment
- Name prompt with duplicate-name (409) retry loop
- Stop flow with "Unable to deploy function" when preview returns errors
- Extract shared preview-table utilities from init.ts into preview-table.ts
- 11 test cases covering success, JSON, picker, errors, and edge cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d boolean param

- Extract `deployJsonMode`, `deployInteractive`, and `tryPreview` from
  the main handler to reduce cognitive complexity (typescript:S3776).
- Replace `assertDraftSelectionAllowed(jsonMode?)` boolean-param function
  with `assertInteractiveTerminal()` that only checks TTY (typescript:S2301).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cription

Sonar flagged `/\s+\S*$/` as super-linear due to backtracking.
Use `lastIndexOf(' ', 50)` instead — same word-boundary cut, O(n).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge origin/main to bring in 110 files of changes. Conflicts resolved
in 5 files by keeping the feature branch's function-type additions
while incorporating main's non-conflicting updates (UI apps GA).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…unction

chore: sync main into features_set-dp-function
Add app-linking step to `function deploy` and `function init` flows.
After a function is created, it is linked to the selected app via
POST /v3/app-store/app-functions. Adds --app-id flag to deploy for
non-interactive use, and an interactive app picker when omitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract selectFunctionApp/tryLinkFunctionToApp into select-app.ts,
  used by both deploy.ts and init.ts (review point 3)
- Fix --json output corruption: link runs silent, spinner uses
  { silent: true }, no logInfo to stdout (point 1)
- Add linked/app_id to JSON payload so callers can detect link
  status (point 2)
- Move app picker after preview+confirm to avoid wasted round-trips
  on early failure (point 4)
- Remove appId! non-null assertion — narrowed via control flow (point 5)
- Log link error detail behind isDebug via logDebug (point 6)
- Add 5 new tests: --app-id path, --json without --app-id, link
  failure in JSON mode, no-apps throw, link failure warning (point 7)
- Fix template literal + concatenation mix in app name display (point 8)
- Add changeset for new --app-id flag (point 8)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move isDuplicateNameError, executePreview, tryPreview, and the
name-confirm-deploy loop into deploy-helpers.ts. Both deploy.ts
and init.ts now delegate to these shared functions, parameterized
by message constants. This addresses the SonarCloud duplication
quality gate (11.2% → well below 3%).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Generalize executePreview to accept templateArgs (draft_id or
  template_id) so init.ts templateFlow uses the shared function
  instead of an inline duplicate.
- Fix nested template literal in select-app.ts (S4624).
- Extract test setup into setupHappyPath() helper to reduce
  duplicated mock boilerplate across 16 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the `brevo function` surface out of the `__BREVO_PREVIEW__` build
gate so it ships in every published build. This follows the same
pattern as the UI-apps GA transition (BEX-290).

Changes:
- Flip FEATURE_STAGE['brevo-function-type'] from 'preview' to 'ga'
- Move function group definition from preview-definitions.ts to
  definitions.ts (always-defined, no longer conditional)
- Add function handler imports directly in definitions.ts
- Remove __BREVO_PREVIEW__ guard from bin/index.ts, help.ts, create.ts
- Move all FUNCTION_* strings from preview-messages.ts to en.ts
- Add GA markers (listFunctionCommand, initFunctionCommand,
  deployFunctionCommand) to scripts/build.mjs
- Update tests to reflect the GA state

Verified: yarn test (1513 pass), yarn build (public), PREVIEW=1 yarn
build (preview), yarn lint, yarn format:check — all clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
piyushsarin-sib and others added 3 commits September 3, 2026 12:23
Extract shared function state-change pattern (ID resolution, spinner,
404 handling, JSON/card output) into buildFunctionActionCommand helper.
Activate and deactivate become thin config wrappers; delete delegates
execution while keeping its confirmation prompt. Shared logic is tested
once in function-action.test.ts, individual tests verify wiring only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: resolve SonarCloud duplication in function action commands
Comment thread src/__tests__/commands/function/function-action.test.ts Fixed
satyamdev10 and others added 2 commits September 4, 2026 13:21
… tests

Extract resolveFunctionId and withNotFoundHandling helpers for get.ts,
deduplicate smoke test cleanup with deleteAndAssert and toggle helpers,
and remove unused import flagged by code-quality bot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: reduce SonarCloud duplication in function commands and smoke tests
Comment thread .github/workflows/smoke-pre-merge.yml
Comment thread src/templates/files/app-config.json.tmpl
Add explicit `app_type` field ('oauth', 'ui', or 'function') to the
scaffolded app-config.json so the app type is immediately visible
without relying solely on the presence of discriminator blocks.

Addresses PR #100 review comment by @piyush.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@piyushsarin-sib piyushsarin-sib left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review

Overall the brevo function group is well built: consistent --id / picker / non-TTY / --json handling across every subcommand, a clean standalone SSE reader, and good unit coverage on the function commands. Requesting changes because the third app type is only half-wired into the CLI, and two repo rules (changeset, agent docs) are not met. Details inline; the two findings with no single anchor line are below.

No changeset, no agent-doc update (blocking)

.changeset/ has no pending file for this branch (one was explicitly removed in chore: remove changeset file), and neither agent-context/SKILL.md nor agent-context/AGENTS.md mention brevo function, the fn alias, the new Brevo Function choice in app create, or the "init requires an interactive terminal" rule. CLAUDE.md makes both hard requirements for new user-facing commands, and an installed skill will otherwise keep telling agents these commands do not exist. Please add a minor changeset and document the surface in both files.

Recommendations

  • Test the app create Function path end to end. The only create test change asserts the prompt shows three choices. Nothing asserts the brevo_function: {} payload, the rendered app-config.json, or that the OAuth feature scaffold is not offered to a Function app. An app upload test on a scaffolded Function config would have caught the registry gap flagged inline.
  • CLAUDE.md's app-type text is now stale. It still describes "the two app types" and the registry comment says "three, soon". Once the registry gains the Function type, add a short Brevo Functions section and update the discriminator wording.
  • Fill in the PR body. It is empty. With ~40 commits from eight sub-PRs squashed in, reviewers need the surface summary, the new BREVO_TEST_API_KEY_FUNCTION secret requirement, and the dedicated smoke account dependency in writing.
  • SonarCloud gate is red on new duplicated-lines density (7.7% vs 3%). The inline notes on function-action.ts and the duplicated message tables should bring it under.

Comment thread src/commands/app/create.ts
Comment thread src/api/sse-stream.ts
Comment thread src/lib/help.ts
Comment thread src/lib/help.ts
Comment thread src/services/function.ts Outdated
Comment thread src/commands/function/function-action.ts Outdated
Comment thread src/commands/function/init.ts
Comment thread src/templates/index.ts Outdated
Comment thread tsconfig.eslint.json
Comment thread src/__tests__/commands/function/function-action.test.ts Outdated
satyamdev10 and others added 7 commits September 4, 2026 14:12
- Add `function` to app-type registry with positive `brevo_function`
  detection on both config and record paths
- Add `function` row to capability matrix (no OAuth flow, no redirect
  URIs, no account-install)
- Add `brevo_function` field to `OAuthApp` type and `AppRecordLike`
- Add `brevo function deploy` to help section
- Replace IIFE with `resolveFunctionId` in `executeFunctionAction`
- Add pagination to `fetchFunctionList` for >50 functions
- Wire `ensureFresh` into `SSEStreamDeps` for token refresh before
  SSE connections
- Expose `runEnsureFresh()` on `ApiClient`, plumb through container
- Fix comment in templates/index.ts (`brevo_function` is mutually
  exclusive with oauth, not orthogonal)
- Add explanatory comments in init.ts, tsconfig.eslint.json, help.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Config backward compat: legacy configs without app_type parse
  correctly (field is undefined, not an error)
- Config round-trip: app_type survives writeProjectConfig, and legacy
  configs without it stay absent after write-back
- Wire isolation: app_type never leaks into the upload payload
  (UploadAppPayload has no app_type field)
- Template rendering: brevo_function branch renders app_type correctly,
  all three app types produce the right value
- Capability matrix: function type has no OAuth/UI capabilities, only
  review-lifecycle on public distribution
- Record resolution: brevo_function record resolves to function type;
  blockless records still resolve to UI (not function)
- Recoverability: function apps are always recoverable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aligns with the existing camelCase convention used by other config
fields (appId, appName, logoUri). The field is local metadata only
and never sent to the server, so this is a config-shape change with
no wire impact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix doc comment in config.ts that said "there is no separate appType key"
- Fix comment in en.ts that said "there is no app-type field"
- Fix AGENTS.md.tmpl that said "There is no appType key"
- Add legacy app_type → appType migration in readProjectConfigAt
- Add 3 migration tests (read migration, write-back cleanup, precedence)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename the informational app-type field from camelCase `appType` back to
snake_case `app_type` to match the wire-mirrored key convention used by
other platform-facing fields (`distribution_type`, `ui_app`,
`brevo_function`). The migration logic now migrates the legacy `appType`
key to `app_type` on read and drops it on write-back.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add app_type to app-config.json and address PR #100 review
@satyamdev10 satyamdev10 changed the title Brevo function feat:Brevo function Sep 4, 2026

@piyushsarin-sib piyushsarin-sib left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Went back through the 13 review threads. All are marked resolved and PR #103 is merged into this branch, so the work did land — but three of the replies claim more than what shipped, and I've re-opened those inline. One repo-rule blocker and one CI note below.

Blocker: agent docs not updated

agent-context/SKILL.md and agent-context/AGENTS.md are untouched by this PR — neither mentions brevo function or brevo fn anywhere. CLAUDE.md is explicit that new commands are user-visible behaviour and both files must be updated in the same PR, and that a feature going GA has to land its reference docs in the GA PR. This adds seven commands, a group alias, and a third app type straight to GA, so it needs both files before merge.

SonarCloud: the gate is red, but the analysis is stale

The gate reports new_duplicated_lines_density at 7.7% against a 3% threshold — the same figure as before the dedup work. SonarCloud's last analysis on this PR is dated 2026-09-03 at commit b2134ac, which predates #101, #102 and #103. So the dedup hasn't actually been measured yet and the checked "SonarCloud quality gate" box in the description isn't supported either way. Worth re-running before merge so we know whether it's fixed.

Re-opened inline (was marked resolved)

  1. Highbrevo app upload is still broken for a Function app. The registry half landed; upload.ts is unchanged and still branches on isUiAppConfig.
  2. Medium — only one of the two list reads was paginated; drafts still cap at 50, which makes fn deploy --id report a false not-found.
  3. Medium — the SSE 401 mapping. ensureFresh landed, the 401 path didn't.

New

  • The new pagination loop can spin forever on a short page; has_more is still unread.
  • detectRecord assumes the server echoes brevo_function on the app record — worth confirming, since that's what decides whether app list and scaffold bootstrap treat a Function app correctly.
  • SSE reader is released without being cancelled.
  • oauthAppType.detectRecord gained a condition no caller exercises.
  • --json on function init can only error.

Nits

  • The description says --drafts; the flag is --draft.
  • Three user-facing strings live outside src/lang/en.ts: Description: (init.ts:324), Name: (deploy-helpers.ts:145), 'Untitled Function' (deploy.ts:75). Spinner labels are inline elsewhere in the repo so those are fine as-is; these three aren't.
  • help.ts's gatedSection('brevo-function-type', ...) — the comment now honestly says the definitions carry no requires, so the emergency flip back to preview it describes wouldn't actually gate the commands. Fixing the comment rather than the gate is defensible, but it's worth making that call explicitly rather than by omission.
  • fn init's iterate loop offers only update / save, with no way out short of Ctrl-C.

Comment thread src/app-types/function/index.ts
Comment thread src/app-types/function/index.ts
Comment thread src/services/function.ts Outdated
Comment thread src/services/function.ts Outdated
Comment thread src/commands/function/deploy.ts
Comment thread src/api/sse-stream.ts
Comment thread src/api/sse-stream.ts
Comment thread src/app-types/oauth/index.ts
Comment thread src/commands/definitions.ts
piyushsarin-sib and others added 5 commits September 4, 2026 16:09
…e with legacy migration (#104)

* refactor(config): normalize app-config.json keys to snake_case with legacy migration

Rename the camelCase keys in app-config.json to snake_case, matching the
wire contract: appId → app_id, appName → app_name, logoUri → logo_uri,
appType → app_type, auth.redirectUris → auth.redirect_uris. The
ProjectConfig interface now IS the file shape, so every read site was
found by the compiler.

Backward compatibility: readProjectConfigAt folds the legacy camelCase
keys (and the older auth.redirectUrls) through one alias table, drops
them from the returned object, and warns once on stderr when a file
carries both spellings with different values.

Migration on write: create/upload/scaffold/start now emit snake_case
only. upload and scaffold also rewrite an in-sync legacy file on their
no-op paths via migrateProjectConfigKeys(), so one run migrates a
project regardless of drift. Values are never changed.

Also: template, scaffold docs, agent-context docs, README, smoke scripts
(accept both spellings so published-build runs still pass), tests for
camelCase-only / snake_case-only / mixed reads and the write-back
migration, and a changeset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(config): announce key migration on every rewrite and add agent migration note

Print the snake_case migration notice whenever a legacy app-config.json is
rewritten — after an upload push and after a consented scaffold refresh,
not only on the no-op paths — and word it so users know to update their
own scripts that read the file. Add an explicit migration rule to
agent-context/SKILL.md and AGENTS.md so agents steer custom code to the
new key names and never write the camelCase names.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(upload): assert the block error pre-empts the app_type label check

Pin the ordering `assertAppTypeAgrees` documents: a config that is BOTH
mislabelled and structurally broken must report the structural problem, so a
partner is never sent off to fix a label only to hit the real refusal on the
next upload. Asserted positively (the entry-named `.label:` error) plus an
explicit check that the message does not mention `app_type`, rather than via
`rejects.not.toThrow`, which can pass for the wrong reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: describe app_type as a validated label, not a discriminator

`app upload` now reads `app_type` to check it agrees with the blocks, so three
docs that said the CLI never reads it were wrong as written.

- CLAUDE.md: read for validation, never for detection; the pre-flight ordering
  and why it is last; and the wire decision, which was nowhere stated — the
  field is file-only because `UploadAppPayload` and the create body are closed
  structs built key by key, so nothing strips it and bo-be needs no change.
- The scaffolded AGENTS.md template said "the CLI never reads it". It now says
  what the field is for and that a hand-edited block needs the label updated.
- agent-context/SKILL.md and AGENTS.md documented the key but not its meaning;
  both now carry the same paragraph, kept in sync per the repo rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(changeset): fold the snake_case entry into the branch's single changeset

CLAUDE.md asks for one changeset file per branch, appended to rather than
multiplied. Merges the separate snake_case file into the existing one and adds
the app_type agreement check. Bump level stays `minor` — both entries already
warranted it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
- Add Brevo Functions documentation to SKILL.md and AGENTS.md (was
  missing entirely — agents had no knowledge of the function commands)
- Fix `brevo app upload` for Function apps: skip redirect_uris check,
  send `brevo_function: {}` on the wire, omit `auth` block, handle
  write-back and diff rendering correctly for the third app type
- Paginate `fetchDraftFunctionList` (was capped at 50, causing silent
  truncation and false not-found errors in `brevo fn deploy --id`)
- Fix `fetchFunctionList` pagination loop: use `has_more` + empty-page
  guard instead of `total` comparison to prevent infinite loops
- Refactor `executeFunctionAction` to delegate to `withNotFoundHandling`
  instead of re-implementing the 404 catch block (Sonar duplication)
- Move hardcoded strings (`Description:`, `Name:`, `Untitled Function`)
  to `src/lang/en.ts`
- Remove unused `functionService` mock from function-action.test.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge the snake_case config key rename (redirect_uris, app_id) from
the base branch with the function-app upload support from this branch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: address remaining PR #100 review comments for brevo function
…key (transition step) (#106)

feat(json): emit snake_case twins for every camelCase --json key (transition step)

Machine-readable output had two conventions: pass-through commands
(app list, app submit, function *) emit the wire's snake_case, while
CLI-built objects (create, upload, credentials, install, delete, whoami,
the error envelope) emit camelCase. app-config.json settled on
snake_case in BEX-470, and scripts should be able to read one spelling
everywhere.

Renaming outright would break every `jq .appId` in a pipeline with
nothing the CLI could migrate, so this is the deprecation step:
jsonOutput() now adds a snake_case twin after each camelCase key at the
top level of every document (per element for arrays) and inside the
error envelope. redirectUri / redirectUris alias to the wire name
redirect_uris. Nested objects are left untouched — they are wire records
or user data. Nothing is removed; camelCase goes away in the next major.

Agent docs and the changeset carry the deprecation note; the seven tests
that pinned exact camelCase shapes now pin both spellings.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
6.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@piyushsarin-sib piyushsarin-sib left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@piyushsarin-sib
piyushsarin-sib merged commit 4379784 into main Sep 4, 2026
5 of 6 checks passed
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.

2 participants