Install for my organization and Connect Slack on the Connections table
ended on an empty screen with only a Return button. The screen declared
a view field (authorizeUrl) but no component, and a frontend step shows
only the components it declares. The screen is now an HTML component:
one sentence about what happens, a Continue to Slack link to the consent
page (same tab, so Slack can return the browser) and the lifetime of the
link, read from SlackOAuthState.LIFETIME_SECONDS (10 minutes).
After Slack, the callback redirected to /preferences?section=slack,
which the host UI does not serve. It returns to
/app/preferences?section=slack with &result=connected or &error=<code>.
Connecting in an environment without the public URL or the Slack app
secrets failed with "IllegalArgumentException (Slack public URL is
required)" or "Slack secret unavailable". It is refused before any state
is issued with a user-facing message that says Slack is not set up in
this environment, which of the two is missing, and the names of the
missing environment variables, never a value.
The Preferences action still answers with the authorize address as the
whole message: core has no redirect field on an action result.
qqq-frontend-next opens a message that is only an https address.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Replace the platform-ci release callers with one caller of
KofTwentyTwo/ci-workflows maven.yaml (qqq-orb port).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Seven tables (workspace, connection, channel, user group, template, message,
attempt), enums, joins, child lists and Postgres DDL. Owner locks on
connection and message; the host tenant lock on workspace and inherited by
join; token fields PASSWORD, hidden, and DENY-locked for every user session.
Tests: validator, owner isolation, two-tenant isolation, token invisibility.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keys from named environment variables (current and previous), generic errors
with no cause, a canary test that a fake token never escapes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Coordinates com.kingsrook.qbits:qbit-slack, qbit-build-parent 2.1.1 with
guardrails enforced, qqq-orb 0.6.9, QQQ 4.1.0-RC.6, Checkstyle and the
JaCoCo gate. Minimal SlackQBitProducer and SlackQBitConfig with a test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>