Commit Graph

830 Commits

Author SHA1 Message Date
Peter Steinberger e7d7075865 test: stabilize extension lifecycle isolation (#126309)
* test(msteams): synchronize SDK stream lifecycle

* test(plugins): preserve error runtime exports in mocks
2026-08-19 04:56:42 -07:00
Peter Steinberger a6b77ffc07 fix(msteams): preserve replies after durable ingress replay (#126169)
* fix(msteams): preserve replies across ingress replay

Recovered Teams channel and group-chat responses now preserve reply and quote context across durable ingress replay. Discovery metadata also advertises the existing group and reaction capabilities.

* chore(msteams): document replay assertion safety

* test(msteams): normalize replay delivery errors
2026-08-18 22:22:13 -07:00
Peter Steinberger 3eecab1bee refactor(plugins): adopt shared retry runtime (#126065) 2026-08-18 17:46:38 -07:00
Peter Steinberger eb38d5e486 fix(reply): report settled delivery outcomes once (#124773)
* refactor(reply): publish settled dispatch receipts

* refactor(reply): isolate dispatch outcome accounting

* refactor(discord): infer settled dispatch result

* test(reply): model settled dispatch receipts

* test(reply): type settled receipt fixtures

* test(telegram): declare settled final receipt

* test(telegram): adapt legacy dispatch fixtures

* fix(reply): complete settled receipt compatibility

* test(channels): keep delivery suite within lint budget

* test(channels): reuse settled count fixture

* test(channels): consolidate receipt assertions

* test(channels): extract delivery receipt fixtures

* fix(qa): recover stopped clients after config restart

* fix(reply): settle deferred delivery receipts

* test(channels): share delivery turn fixtures

* fix(channels): preserve non-visible reconciliation

* fix(reply): preserve settled receipt compatibility

* refactor(reply): make settled receipts canonical

* refactor(reply): absorb settlement at dispatcher boundary

* test(matrix): prove settled receipt precedence

* refactor(sessions): extract prompt snapshot types

* fix(reply): restore queued admission counts
2026-08-17 06:38:16 -07:00
Peter Steinberger fcb499a4ce refactor(channels): move read-gate policy to channel plugins (#125136)
* refactor(channels): move read-gate policy to plugins

* test(channels): declare bundled Discord read gates
2026-08-17 01:38:30 -07:00
Peter Steinberger fb0e8b145e refactor: consolidate final mechanical audit paths (#125165) 2026-08-17 01:30:21 -07:00
Peter Steinberger 1027837d96 fix(msteams): avoid ambiguous delivery replay (#125127) 2026-08-17 00:13:59 -07:00
Peter Steinberger f9b1ccc4fa refactor(plugin-sdk): discriminate delivery and exec results (#124979)
* refactor(plugin-sdk): discriminate delivery and exec results

* test(plugin-sdk): update delivery target expectations

* fix(outbound): preserve canonical delivery targets

* fix(irc): normalize message delivery target
2026-08-16 22:55:41 -07:00
Peter Steinberger 568b920b21 feat(lint): enforce import ordering and deduplication (#124730)
* refactor(imports): dedupe and hoist imports

* feat(lint): enforce import/no-duplicates and import/first
2026-08-16 11:44:52 -07:00
Peter Steinberger 63401b730b fix: keep doctor security conditions as single findings (#124666)
* fix(doctor): record security finding severity

* refactor(security): keep audit severity internal

* fix(security): preserve channel finding severity
2026-08-16 10:24:40 -07:00
Peter Steinberger ea77e21646 perf(test): remove ingress capacity waits (#124630) 2026-08-16 07:15:33 -07:00
Peter Steinberger 5d601233df refactor(types): remove chained type assertions in extensions (#124079)
* refactor(types): remove chained assertions in extensions

* fix(codex): preserve canonical binding identity
2026-08-15 01:39:26 -07:00
Peter Steinberger f0d277277b test(perf): assert live duplicate tombstones (#124012) 2026-08-14 21:45:48 -07:00
Peter Steinberger 81e0cf0d1d test: replace ingress waits with stop barriers (#123990) 2026-08-14 20:59:52 -07:00
wanyongstar 9386ac0966 fix(msteams): dedupe poll vote selections before maxSelections truncation (#123070)
* fix(msteams): dedupe poll vote selections before maxSelections truncation

normalizeMSTeamsPollSelections truncated the raw selections to
maxSelections before deduplicating, so a duplicated choice (e.g. an
Adaptive Card posting "0,0,1") consumed multiple slots and starved
later distinct choices: with maxSelections=2 the stored vote became
["0"] and choice "1" was silently dropped. Deduplicate first, then
truncate.

* fix(msteams): simplify poll selection normalization

---------

Co-authored-by: ClawSweeper <steipete+clawsweeper@gmail.com>
2026-08-14 08:43:41 -07:00
Josh Avant 97a53a9b35 feat: audit admitted channel participant identity (#122863)
* feat: audit admitted channel participant identity

* fix: preserve Telegram identity through thread recovery

* fix: signal held gateway process groups

* fix: keep audit evidence passive in collect routing

* fix: validate copied channel participant evidence

* fix: bind channel participant evidence to host ingress

* fix: honor Telegram proof credential roles

* fix: restart held Telegram proof through gateway

* fix: repair channel identity CI regressions

* test(matrix): bind thread routing owner

* fix: preserve direct DM SDK compatibility

* fix: bind channel provenance at host runtime

* test(feishu): provide channel context builder

* fix: defer record-bound channel runtime resolution

* fix: keep channel admission evidence core-private

* fix(audit): bind channel admission to plugin lifecycle

* fix(audit): bind ingress provenance to final context

* refactor(audit): split admission scope keys

* test(queue): cover combined metadata carriers

* refactor(audit): keep lifecycle helpers private

* fix(queue): preserve combined turn authority

* test(channels): provide ingress context builders

* test(channels): align integrated CI fixtures

* test(clickclack): resolve model-loop ingress

* docs: preserve channel participant evidence invariant
2026-08-14 08:57:01 -05:00
joshavant 59c382b717 fix(tests): respect plugin helper boundary 2026-08-13 01:34:05 -05:00
joshavant 13750feff3 fix(plugin-sdk): preserve cancellation receivers 2026-08-13 01:34:05 -05:00
joshavant 5af3d49621 fix(plugin-sdk): make ingress cancellation fan-in safe 2026-08-13 01:34:05 -05:00
Peter Steinberger 08f9c3a5cb test(extensions): remove duplicate runtime replays (#122949) 2026-08-12 19:58:04 -07:00
Daniel Cárdenas 326501fce3 fix(msteams): honor inbound channel media limit (#122315)
* fix(msteams): honor inbound channel media limit

* test(msteams): update lifecycle runtime mock

* style(msteams): avoid resolver config shadowing

* style(msteams): format lifecycle resolver mock

* refactor(msteams): inline media fallback

---------

Co-authored-by: DanielCardenas <djerez@lean-tech.io>
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 19:06:47 -07:00
Peter Steinberger c23d66e3b5 refactor: consolidate coercion ownership (#122692)
* refactor: consolidate coercion ownership

* test: align shard check with weighted planning

* chore: refresh plugin SDK API baseline
2026-08-12 09:25:28 -07:00
Peter Steinberger 40cb6f0e3b feat(ui): keep Where picker destinations live (#122531)
* feat(gateway): enrich environment summaries

* chore(sdk): refresh plugin API surface

surface drift approved: additive EnvironmentSummary enrichment (runners plan rev 2, milestone 4)

* feat(ui): keep where picker destinations live

* docs: link picker liveness milestone PR

* fix(ui): deduplicate picker locale keys

* test(ui): update picker section expectations

* fix(ssrf): narrow lookup resolver contract

* fix(gateway): publish authoritative environment facts
2026-08-12 05:11:46 -07:00
Peter Steinberger b080dd1e76 refactor: consolidate coercion contracts (#122458)
* refactor: consolidate coercion contracts

Centralize exact string, record, numeric, date, Boolean, argument, and structured-error coercions while preserving call-site semantics.

Migrate canonical-name collisions and deprecated internal SDK bypasses, deleting 55 net production/tooling lines. Expand declaration ownership enforcement to 101 allowed helpers and add a narrow export-completeness audit.

* fix: preserve standalone script coercions

Keep copied Control UI tooling self-contained and retain the trusted release harness module-relative source seam when the harness runs against an old target cwd.
2026-08-11 23:26:37 -07:00
Peter Steinberger 964c8c84c1 refactor: consolidate coercion ownership (#122299)
* refactor: consolidate coercion ownership

Centralize four canonical coercion helpers, migrate exact core and plugin duplicates through narrow Plugin SDK facades, and enforce declaration and plugin-normalization ownership boundaries.

The sweep adds eight focused SDK exports while deleting more production and tooling code than it adds. User-visible behavior is unchanged except for safer equivalent object and UI parsing at existing boundaries.

* fix: guard integer option ownership

Register resolveIntegerOption with the canonical function owner and extend the declaration-guard fixture so future local duplicates fail validation.

* fix: keep integer helpers on numeric facade

Remove the unshipped duplicate string-coerce exports and route every affected plugin consumer through the existing number-runtime contract.

* fix: point numeric coercion to number runtime

Make boundary and declaration diagnostics recommend the canonical numeric facade, with failing-before coverage for both guidance paths.
2026-08-11 17:14:53 -07:00
Peter Steinberger cad77fb39c refactor: consolidate remaining coercion helpers (#122020) 2026-08-11 10:22:01 -07:00
Ayaan Zaidi 2c8ed54ddb feat(heartbeat): default delivery to the configured owner, never groups (#121988)
Unset heartbeat.target now resolves "owner": elected heartbeat notifications deliver to the operator's DM resolved from commands.ownerAllowFrom or the channel allowFrom (first concrete entry; wildcards and channel-scoped wildcards excluded; configured owners exhausted across channels before any channel-local fallback). Delivery requires the channel's own classifier to positively prove a direct destination — every bundled messaging plugin now ships an inferTargetChatType contract — and unproven or group-shaped destinations fail closed to the visible no-route state. The first implicitly-routed delivery carries a one-line self-explanation naming the target: "none" opt-out. Explicit target "last" remains as the follow-the-conversation opt-in. Refines the unreleased #121892 default before it ships; refs #121880.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 13:18:22 +00:00
Ayaan Zaidi 4c951398ef fix(messages): keep runtime details out of chat alerts (#121600)
Keep raw commands, paths, and provider errors out of ordinary chat while preserving explicit raw diagnostics and structured admin history.

Default command progress is status-only; `/verbose full` and `commandText: "raw"` retain diagnostic detail.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-10 21:37:48 +05:30
Pavan Kumar Gondhi d85f5c1176 fix(msteams): fail closed on denied group access (#121086) 2026-08-10 10:39:22 +05:30
Peter Steinberger 3bdfd60caa fix(media): accept mixed-case local file URLs (#121226) 2026-08-09 16:40:55 -07:00
Peter Steinberger 10e60fa0ce refactor(plugins): shared legacy-state doctor migration and simple secret contracts (#120346)
* refactor(plugins): share legacy JSON doctor migration

* refactor(discord): share account token inspection cascade

* refactor(plugins): share simple channel secret contracts

* refactor(discord): keep token inspector private
2026-08-07 13:55:31 -07:00
Josh Avant c691f2e41c fix(progress): preserve callback acceptance results (#120171)
* fix(progress): preserve callback acceptance results

* fix(progress): require transport acknowledgements

* fix(progress): preserve direct acceptance outcomes
2026-08-07 14:40:33 -05:00
Vincent Koc 5f585a57bd test(msteams): cover occupied webhook port (#120158)
Punchcard-Session: silver-willow-harbor-px
2026-08-07 13:46:41 +08:00
Peter Steinberger 9aa24e8f2e refactor(test): replace logic-bearing vi.mock factories with boundary fakes, batch 2 (#120117)
* refactor(test): exercise real Teams monitor lifecycle

* refactor(test): use real gateway lifecycle state

* refactor(test): use real restart delivery queue

* test: type Teams SDK boundary fixture
2026-08-06 22:02:50 -07:00
Peter Steinberger c663c39763 refactor(test): table-drive exact-duplicate test blocks, batch 2 (#120071)
* refactor(test): table-drive tooling test cases

* refactor(test): table-drive agent test cases

* refactor(test): table-drive core test cases

* refactor(test): table-drive plugin test cases

* refactor(test): table-drive package test cases

* chore(test): prune max-lines baseline

* fix(test): preserve table row literal types
2026-08-06 17:00:28 -07:00
Alix-007 819f92bba5 fix(msteams): reject malformed OAuth token envelopes [AI-assisted] (#111638)
* fix(msteams): reject malformed OAuth token envelopes

* refactor(msteams): reuse canonical record guard
2026-08-06 03:57:33 +00:00
Peter Steinberger 1f0269eda5 refactor(msteams): consolidate channel action target resolution (#119632)
* refactor(msteams): consolidate channel action target resolution

* fix(msteams): honor configured group read policy

* fix(msteams): explain delegated channel access recovery
2026-08-05 10:52:13 -07:00
Peter Steinberger 2d1242556e test(msteams): serve JWKS from in-process server in auth coverage (#119354)
* test(msteams): serve JWKS from in-process server in auth coverage

The Entra/service-token validator tests spied JwksClient.prototype on the
jwks-rsa copy the test file imports, but the SDK's internal
require("jwks-rsa") resolves a different physical copy and vitest cannot
intercept a CommonJS require inside node_modules — so the spy missed and
the tests hit the real login.botframework.com / login.microsoftonline.com
JWKS endpoints (JwksError: Bad Request, SigningKeyNotFoundError).

Replace the mock with a real JWKS document served from an in-process
node:http server, pointed at via the SDK's own endpoint overrides
(openIdMetadataUrl cloud override for the service validator, loginEndpoint
for the Entra factory). The v2-issuer acceptance test drives the underlying
JwtValidator with a decoupled jwksUriOptions {type:'uri'} so issuer
validation uses the real login host while keys come from the local server.
Deterministic, no external network, and exercises the real fetch + RS256
verify path.

* test(msteams): fix cloud-environment import and drop unused jwks-rsa

The extensions test-types gate resolves @microsoft/teams.api's dual
.d.ts/.d.mts types strictly and does not see the root re-export of
withOverrides/PUBLIC (TS2305), so import them from the canonical
auth/cloud-environment subpath the SDK itself uses. The JWKS-server rework
also removed the last direct jwks-rsa import, so drop the now-unused
devDependency and refresh the lockfile (knip deadcode).

---------

Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
2026-08-04 15:34:38 -07:00
Peter Steinberger 467492b125 fix(msteams): enforce documented AAD owner approval principals (#118967) 2026-08-03 14:24:30 -07:00
Peter Steinberger be9a34a79d fix(msteams): enable channels for federated environment credentials (#118931) 2026-08-03 13:57:08 -07:00
Peter Steinberger f9d9d1225a refactor(channels): own the lifecycle status contract in SDK patch factories (#118795)
* refactor(sdk): add channel lifecycle patch factories

* refactor(channels): adopt lifecycle patches in a-m

* refactor(channels): adopt lifecycle patches in n-z

* refactor(runtime): lifecycle-own ambient registries

* test(slack): assert lifecycle factory fields

* fix(sdk): preserve lifecycle patch extras types

* test(zalouser): widen lifecycle status sink

* test(irc): avoid shadowed status patch

* fix(zalo): reuse account-agnostic media route

* fix(gateway): accept explicit channel ready recovery

* test(qa): assert terminal Slack block fact

* test(qa): restore Slack blocked lifecycle scenario

* test(gateway): lock explicit lifecycle recovery contract
2026-08-03 12:39:48 -07:00
Peter Steinberger 4c66ed5615 feat(channels): lifecycle wave 2 — fifteen more channels publish recorded lifecycle (#118298)
* feat(channels): publish lifecycle from existing status sinks

* feat(channels): thread lifecycle through provider monitors

* fix(mattermost): keep lifecycle status helper private

* fix(matrix): preserve terminal lifecycle during startup cleanup

* fix(matrix): reject invalid tokens during startup

* test(mattermost): drop unused vi import
2026-08-02 17:30:56 -07:00
Peter Steinberger 15560382a2 test(msteams): consolidate Graph upload fixtures (#118268) 2026-08-02 16:15:17 -07:00
Peter Steinberger 6c29fc154f test(msteams): avoid hanging response clones (#118096)
Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
2026-08-02 11:04:38 -07:00
Peter Steinberger a154b4faea refactor: consolidate Teams and error helpers (#117907) 2026-08-02 02:02:17 -07:00
zengLingbiao 83c6a51b0e fix(msteams): cancel unread Graph error response bodies (#117664)
* fix(msteams): cancel unread Graph error response bodies

* fix(msteams): release every guarded Graph response safely

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-02 17:01:30 +08:00
Peter Steinberger ac28f4d558 fix: release channel delivery resources reliably (#117855)
* fix(channels): consolidate delivery lifecycle ownership

* test(msteams): match release mock contract

* test(plugin-sdk): satisfy promise executor lint

* chore(plugin-sdk): regenerate API baseline for delivery-correlation + fetch-runtime exports
2026-08-02 00:24:47 -07:00
Peter Steinberger 996b1e1e86 refactor(plugins): remove oauth pass-through wrappers (#117867) 2026-08-01 23:28:59 -07:00
Jiatai Wang bacc5071db fix(msteams): rename SharePoint uploads on name conflict (#113560)
Bot-generated files reuse names (openclaw runtime emits image-1.png every
generation), so Graph's default conflictBehavior=replace overwrote the prior
same-named driveItem in place. Because Teams caches file cards by driveItem
URL, channels kept showing the stale file and earlier content was lost from
OpenClawShared.

Force @microsoft.graph.conflictBehavior=rename on the simple upload so
SharePoint mints a uniquely-named driveItem (fresh name/eTag/URL) on
collision. The existing getDriveItemProperties re-read by item id already
surfaces the new name/URL to the Teams file card, so no downstream change is
needed.

Closes #112368

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-01 22:59:44 -07:00
Peter Steinberger d6e537a859 refactor(channels): share persistent state error reporting (#117813) 2026-08-01 22:06:25 -07:00