Hustler-Stufe: Keller begehbar ab Stufe 3, Bot-Leads abrufbar erst ab Stufe 6

Die Stufen-Sperre trennt jetzt zwei Dinge: KELLER_BEGEHBAR_AB = 3 (Keller-Etage als Link,
?tab=botleads gueltig, Spur-Links in den Keller) und BOTLEADS_AB = 6 (Abruf von GET /botleads).
kellerOffen/STUFE_KELLER entfallen, dafuer kellerBegehbar() und botleadsAbrufbar().
workersApi.botleads bleibt unter Stufe 6 hart gesperrt, der Text heisst nun
BOTLEADS_GESPERRT_TEXT. Die Keller-Ansicht selbst (leeres Register ohne Abruf) folgt im
naechsten Commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-22 12:21:59 +00:00
1 parent 8363b63374
commit 6eb4dd3c51
11 files changed
+121 -82

No files matched your search

+4 -4
View File
@@ -385,8 +385,8 @@ test('Spur-Links: unsichere (javascript:, //host, /\\host, data:) bleiben Text;
})
})
// Stufen-Sperre (hustlerStufe.js): unterhalb der Keller-Stufe (6) führt auch kein Spur-Link in den Keller; der Eintrag bleibt als Text stehen
test('Spur-Links in den Keller (?tab=botleads, auch über /workers und /leads) sind auf Stufe 3 Text und ab Stufe 6 Router-Links; alle anderen Links bleiben', async () => {
// Stufen-Sperre (hustlerStufe.js): unterhalb von Stufe 3 (KELLER_BEGEHBAR_AB) führt auch kein Spur-Link in den Keller; der Eintrag bleibt als Text stehen
test('Spur-Links in den Keller (?tab=botleads, auch über /workers und /leads) sind auf Stufe 1 und 2 Text und ab Stufe 3 Router-Links; alle anderen Links bleiben', async () => {
const events = [
{ id: '1', ts: '2026-10-22T09:00:00Z', text: 'Keller', link: '/hustler?tab=botleads&bot=abc123' },
{ id: '2', ts: '2026-10-22T08:59:00Z', text: 'Alt', link: '/workers?tab=botleads&bot=abc123' },
@@ -396,7 +396,7 @@ test('Spur-Links in den Keller (?tab=botleads, auch über /workers und /leads) s
{ id: '6', ts: '2026-10-22T08:55:00Z', text: 'Extern', link: 'https://example.org/hustler?tab=botleads' },
]
const ziele = (li) => nodes(li, (n) => n.tag === 'a' || n.tag === 'router-link')
for (const stufe of [1, 3, 5]) {
for (const stufe of [1, 2]) {
await lauf({ props: { workerId: 'lea', stufe }, trace: { trace: { events }, loading: false, error: null } }, (ui) => {
const zeilen = ui.spurZeilen(); const byText = (t) => zeilen.find((z) => z.text === t)
assert.equal(zeilen.length, 6)
@@ -407,7 +407,7 @@ test('Spur-Links in den Keller (?tab=botleads, auch über /workers und /leads) s
assert.ok(!JSON.stringify(ui.find((x) => x.tag === 'a' || x.tag === 'router-link').map((n) => n.props)).includes('botleads&bot'))
})
}
for (const stufe of [6, 9]) {
for (const stufe of [3, 5, 6, 9]) {
await lauf({ props: { workerId: 'lea', stufe }, trace: { trace: { events }, loading: false, error: null } }, (ui) => {
const zeilen = ui.spurZeilen(); const byText = (t) => zeilen.find((z) => z.text === t)
assert.deepEqual(ziele(byText('Keller').li).map((n) => n.props.to), ['/hustler?tab=botleads&bot=abc123'])