Files
bDS2/specs/menu.allium

74 lines
2.3 KiB
Plaintext

-- allium: 1
-- bDS Navigation Menu
-- Scope: core (read for rendering), extension Bucket F (menu editor UI)
-- File-only model: no DB table. Loaded from meta/menu.opml into a
-- transient value, mutated in memory, written back to OPML on save.
surface MenuManagementSurface {
facing _: MenuOperator
provides:
MenuLoadRequested(project_id)
UpdateMenuRequested(items)
SyncMenuFromFilesystemRequested(project_id)
}
value MenuItem {
kind: page | submenu | category_archive | home
label: String
slug: String? -- pageSlug for page/home, categoryName for category_archive
children: List<MenuItem>? -- present only for submenu kind
}
value Menu {
items: List<MenuItem>
-- Derived
home_entry: items.first -- always home after normalization
}
surface MenuSurface {
context menu: Menu
exposes:
menu.items.count
menu.home_entry.label
}
invariant HomeAlwaysFirst {
-- Normalization guarantees home is always the first item.
-- UpdateMenu strips any home entries from input, then prepends one.
for menu in Menus:
menu.items.first.kind = home
}
invariant MenuPersistedAsOpml {
-- meta/menu.opml is the sole persistent store (no DB table).
-- OPML outline attributes: text (label), type (kind),
-- pageSlug (slug for page/home), categoryName (slug for category_archive).
-- Nested <outline> elements represent submenu children.
parse_opml(read_file("meta/menu.opml")) = menu.items
}
rule LoadMenu {
when: MenuLoadRequested(project_id)
-- Reads meta/menu.opml; if file missing, returns default (home-only) menu.
-- Normalizes: strips home entries from body, prepends canonical home.
ensures: MenuLoaded(project_id, normalize(parse_opml_or_empty(project_id)))
}
rule UpdateMenu {
when: UpdateMenuRequested(items)
-- Normalizes Home entry: strips all home items, prepends canonical home.
-- Writes normalized menu back to meta/menu.opml.
let without_home = items where kind != home
ensures: MenuFileWritten(normalize(without_home))
}
rule SyncMenuFromFilesystem {
when: SyncMenuFromFilesystemRequested(project_id)
-- Reloads menu from OPML, normalizes, writes back (round-trip repair).
ensures: MenuLoaded(project_id, _)
ensures: MenuFileWritten(_)
}