QRun-IO/.github#2 adds a tag-and-release job that signs vX with the
QRUN_TAG_SIGNING_KEY secret after Maven Central confirms the artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The producer read a literal version, so released artifacts reported a stale
or -SNAPSHOT version. qbit-slack.properties (version=${project.version}) is
Maven-filtered and the producer loads it; tests assert producer == bundle ==
artifact version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With no SLACK_* secrets at all the app readiness check is NOT_CONFIGURED and
the health indicator reports UNKNOWN (HTTP 200) with configured=false, so an
optional, unset Slack integration can't fail a readiness probe (it took kof22's
probe down). Not-yet-checked is UNKNOWN too. Partial or invalid configuration
stays DOWN. Tests for all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On release branches the bundle's version and the producer's differed, so the
bundle test that asserts they match failed, and released bundles recorded
SNAPSHOT as their provenance. help/*.yaml is now filtered:
version: ${project.version}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Host-neutral help (deployment-specific facts removed), registered with
HelpBundles, gated by HelpBundleAssertions. QQQ 4.1.0-RC.7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The QBIT_SLACK provider declares its capabilities and returns status, message
id and reasons through core SendMessageOutput; idempotency keys and templates
come from SendMessageInput.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RC.1-RC.3 failed to start on RC.7: the reflection adapter (written against the
#1162 stand-in) called a withSection signature RC.7 doesn't have. Replace it with
SlackPreferencesProvider on the real SPI (section, connections list, Connect,
Install, test message and Disconnect actions, read-only store), registered only
when the core classes exist. Startup test validates the instance on RC.7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 429, 5xx, timeouts and invalid_auth leave channel rows alone, stop the
workspace loop and make the channels check a warning.
- Handle sync needs only usergroups:read.
- Check channels reports warnings and per-row errors; status fields are
read-only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every slack_* table and the app get help bundle text saying how rows get
created. Readiness and a new Check channels action persist the channel's
Slack name, privacy, bot membership, archived, purpose and checked time.
User group handle is resolved from usergroups.list and used in mentions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /qqq/hooks/slack/interactions: verified, acknowledged, token checked
against the stored message, Slack user mapped to a connection in the same
workspace row, process run in that user's session with permission, tenant and
record locks; idempotent message update; ephemeral replies only to
hooks.slack.com. POST /qqq/hooks/slack/events: url_verification,
tokens_revoked and app_uninstalled across every tenant row of the team.
Built-in acknowledge_alert / resolve_alert when those processes exist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0 HMAC-SHA256 over timestamp and raw body, 300 s window, constant-time
compare; button values are server-signed (message, action, record, expiry).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SlackDeliveryDestination: contingent pickers (workspace, then DM to me or a
channel the user is a member of), owner re-authorization, delivery template,
attachments as FILE messages, lookup mapping; built against
STAND-IN(core=QRun-IO/qqq#1205, removeBy=4.1.0-RC.8) copies of the core
delivery types. SlackApi.applySessionKeys so hosts stop using internal
SlackSecurity.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
files.getUploadURLExternal, a streamed upload from core storage (no temp
files), files.completeUploadExternal; expired-lease reconcile by title marker
through files.list; files:read scope added to the manifest and design.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Connections, recent deliveries, readiness and failures as linked tables;
non-zero status tiles linking to filtered Messages; local dates and readable
status labels; Fix hints only when not ready; one title.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nav lists only the six main tables; the home shows the user's connections and
deliveries and, for slack.admin, workspace readiness, outbox counts and recent
failures, all through owner and tenant locks. Test-scope demo server with the
fake Slack server and seeded data for screenshots.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registers only when core user preferences exist:
STAND-IN(core=QRun-IO/qqq#1162, removeBy=4.1.0-RC.8). Connect, Disconnect,
Send me a test message and Install for my organization also work today as
record actions on Connections.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
isInstalled/send/sendOnce/reply/update/lookups/readiness/connectionsFor/
listTargets/ensureTemplate with token-free projections; readiness checks for
app, workspace, connection, registered channels and outbox, Check readiness
action, scheduled refresh; health registered only when qqq-middleware-health is
present.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed, expiring OAuth state bound to user, tenant and session (stateless across
pods; per-pod replay set), callback route via the javalin extension (provided),
row-bound encrypted tokens, Disconnect (auth.revoke) and Uninstall actions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Email-compatible variable language with mrkdwn escaping, Block Kit variables in
string positions only, size and block limits, built-in notification, digest and
delivery templates; PHI/PII variables tokenized or refused, SSN/MRN patterns
refused, SECURITY sends title and link only, canary test.
STAND-IN(core=QRun-IO/qqq#1142, removeBy=4.1.0-RC.8) for classified value tokens.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registered under bridgeProviderName (default slack) so callers use core
SendMessageAction only. STAND-IN(core=QRun-IO/qqq#1194, removeBy=4.1.0-RC.8)
for output status.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claim and lease with attempt rows; re-authorization as the owner at send time;
message-metadata reconcile of expired leases; 429 Retry-After without consuming
attempts; retries, dead letters, FAILED_AUTH with owner notification and alert;
threads, updates, rate limiter, workspace health. Two-tenant and token-leak tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workspace and connection lookups run as the owner (createAutomatedSessionForUser)
so tenant and owner locks apply; conversations.members must include the owner;
bounded membership cache; only the chosen row's token is ever decrypted;
ownerless sends limited to registered channels with a matching tenant.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>