feat(rust): notifications and engagement (phase 10, protocol 7)
Registers the engagement set R7 put in v1: thirteen triggers, four push streams, three audiences, four bodies (two triggers, email and in-app) and thirteen disabled rules in seven groups (PLAN.md §25, D59-D68). The raid alert goes to everyone authorised on the tool cupboard, one emit per linked person with ownerUserId, so the owner ceiling holds per emit. It covers doors and walls (protocol 7), never names the raider, alerts nobody when there is no cupboard, and carries ownerOnline so "offline only" is the seeded rule's condition rather than code. The fan-out runs off ingest before a frame is applied, since applying a disband deletes the roster the notice is sent to. A replayed event is told only while it is news: 15 minutes for broadcasts, 24 hours for personal and staff events. Dedupe keys come from the event, not the sidecar's row id. Server online/offline and a new kills leader are in-memory transitions, never on first sight, and a tie is not a lead. A login with no approval within a minute becomes a staff notice via a query, so a restart loses nothing. Also fixes a phase-4 gap (D68): the refresh now asks /health, so a game that hung, or whose bridge was unloaded, while the sidecar stayed up no longer reads as online. It stops naming players as online, and a stale board no longer moves "last seen". engagement-triggers.json is the committed freeze of all of it, checked in CI with line endings normalised. The check was verified by breaking it both ways. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -137,17 +137,36 @@ test('nothing is registered that has nothing behind it yet', () => {
|
||||
// surfaces an operator can configure and then wait on — worse than an absent
|
||||
// one, because the absence is visible. Each of these arrives with the phase
|
||||
// that has something real to put in it, and this assertion is what that phase
|
||||
// deletes. Phase 9 deleted the Team provider's line.
|
||||
assert.strictEqual(api.record.triggers, null)
|
||||
assert.strictEqual(api.record.audiences, null)
|
||||
assert.strictEqual(api.record.engagementSeeds, null)
|
||||
assert.strictEqual(api.record.streams, null)
|
||||
// deletes. Phase 9 deleted the Team provider's line; phase 10 the four
|
||||
// engagement lines, and the announce leg and post hook it deliberately did
|
||||
// NOT register (D62) moved into the assertions below.
|
||||
assert.deepStrictEqual(api.record.legs, [])
|
||||
assert.strictEqual(api.record.hooks.post, undefined)
|
||||
assert.strictEqual(api.record.eventBudgets, null)
|
||||
assert.strictEqual(api.record.eventOptionSources, null)
|
||||
assert.strictEqual(api.record.eventLeases, null)
|
||||
assert.strictEqual(api.record.eventActions, null)
|
||||
})
|
||||
|
||||
test('the engagement set is registered as one decision (phase 10, R7)', () => {
|
||||
const { api } = register()
|
||||
|
||||
const triggers = api.record.triggers
|
||||
const streams = api.record.streams
|
||||
assert.ok(Array.isArray(triggers) && triggers.length > 0)
|
||||
assert.ok(Array.isArray(api.record.audiences) && api.record.audiences.length === 3)
|
||||
assert.ok(api.record.engagementSeeds && Array.isArray(api.record.engagementSeeds.ruleGroups))
|
||||
|
||||
// A stream is a toggle for a trigger; one with no trigger behind it is a
|
||||
// toggle nothing can ever fire (D65, one namespace across both facets).
|
||||
const triggerIds = new Set(triggers.map((t) => t.id))
|
||||
for (const s of streams) assert.ok(triggerIds.has(s.id), `stream ${s.id} has no trigger`)
|
||||
assert.deepStrictEqual(
|
||||
streams.map((s) => s.id).sort(),
|
||||
['rust.base.destroyed', 'rust.server.offline', 'rust.server.online', 'rust.wipe.started'],
|
||||
)
|
||||
})
|
||||
|
||||
test('the module’s protocol version agrees with the manifest it ships beside', () => {
|
||||
const sidecar = require('../sidecarClient')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user