141 lines
5.0 KiB
Plaintext
141 lines
5.0 KiB
Plaintext
-- allium: 1
|
|
-- bDS Project Metadata, Categories, Publishing Preferences
|
|
-- Scope: core (Wave 1)
|
|
-- Distilled from: src/main/engine/MetaEngine.ts, schema.ts
|
|
|
|
use "./project.allium" as project
|
|
|
|
surface MetadataControlSurface {
|
|
facing _: MetadataOperator
|
|
|
|
provides:
|
|
UpdateProjectMetadataRequested(project, changes)
|
|
AddCategoryRequested(project, name)
|
|
RemoveCategoryRequested(project, name)
|
|
UpdateCategorySettingsRequested(project, category, settings)
|
|
SetPublishingPreferencesRequested(project, prefs)
|
|
AppStarted(project)
|
|
}
|
|
|
|
surface PublishingPreferencesSurface {
|
|
context prefs: PublishingPreferences
|
|
|
|
exposes:
|
|
prefs.ssh_host when prefs.ssh_host != null
|
|
prefs.ssh_user when prefs.ssh_user != null
|
|
prefs.ssh_remote_path when prefs.ssh_remote_path != null
|
|
prefs.ssh_mode
|
|
}
|
|
|
|
value CategoryRenderSettings {
|
|
title: String?
|
|
titles: Map<String, String> -- translated titles keyed by language
|
|
render_in_lists: Boolean
|
|
show_title: Boolean
|
|
post_template_slug: String?
|
|
list_template_slug: String?
|
|
}
|
|
|
|
entity ProjectMetadata {
|
|
project: project/Project
|
|
name: String
|
|
description: String?
|
|
public_url: String?
|
|
main_language: String? -- ISO 639-1
|
|
default_author: String?
|
|
max_posts_per_page: Integer -- 1..500, default 50
|
|
blogmark_category: String?
|
|
pico_theme: String? -- 12+ named Pico CSS themes
|
|
semantic_similarity_enabled: Boolean
|
|
blog_languages: Set<String> -- subset of supported languages
|
|
categories: Set<String> -- category names
|
|
category_settings: Set<CategoryRenderSettings>
|
|
}
|
|
|
|
entity PublishingPreferences {
|
|
ssh_host: String?
|
|
ssh_user: String?
|
|
ssh_remote_path: String?
|
|
ssh_mode: scp | rsync
|
|
}
|
|
|
|
invariant DefaultCategories {
|
|
-- New projects start with: article, picture, aside, page
|
|
-- These are defaults, not invariants — user can remove them
|
|
}
|
|
|
|
invariant MetadataPersistedAsFiles {
|
|
-- Four separate JSON files in meta/:
|
|
-- meta/project.json — name, description, publicUrl, mainLanguage, etc.
|
|
-- meta/categories.json — sorted category list
|
|
-- meta/category-meta.json — per-category render settings
|
|
-- meta/publishing.json — SSH connection details (non-secret)
|
|
-- All writes are atomic (temp file + rename)
|
|
-- JSON is pretty-printed without a trailing newline and uses bDS2/Jason
|
|
-- byte-order key ordering. Project keys are blogLanguages,
|
|
-- blogmarkCategory, defaultAuthor, description, imageImportConcurrency,
|
|
-- mainLanguage, maxPostsPerPage, name, picoTheme, publicUrl,
|
|
-- semanticSimilarityEnabled (nil keys absent). Publishing keys are sshHost,
|
|
-- sshMode, sshRemotePath, sshUser (nil keys absent; sshMode defaults to scp).
|
|
-- Category names and per-category keys are byte-order sorted; per-category
|
|
-- keys are listTemplateSlug, postTemplateSlug, renderInLists, showTitle,
|
|
-- title, titles. The title is for the main language; titles contains
|
|
-- configured translations keyed by language. categories.json uses
|
|
-- case-sensitive byte-order sorting. tags.json
|
|
-- remains case-insensitively name-sorted; entry keys are color, name,
|
|
-- postTemplateSlug and blank optional values are absent.
|
|
}
|
|
|
|
config {
|
|
default_max_posts_per_page: Integer = 50
|
|
min_posts_per_page: Integer = 1
|
|
max_posts_per_page: Integer = 500
|
|
default_categories: Set<String> = {"article", "picture", "aside", "page"}
|
|
supported_pico_themes: Set<String> = {
|
|
"default", "amber", "blue", "cyan", "fuchsia", "green",
|
|
"grey", "indigo", "jade", "lime", "orange", "pink",
|
|
"pumpkin", "purple", "red", "sand", "slate", "violet",
|
|
"yellow", "zinc"
|
|
}
|
|
}
|
|
|
|
rule UpdateProjectMetadata {
|
|
when: UpdateProjectMetadataRequested(project, changes)
|
|
ensures: MetadataFieldsUpdated(project, changes)
|
|
ensures: ProjectJsonWritten(project)
|
|
}
|
|
|
|
rule AddCategory {
|
|
when: AddCategoryRequested(project, name)
|
|
requires: not (name in project.metadata.categories)
|
|
ensures: project.metadata.categories = project.metadata.categories + {name}
|
|
ensures: CategoriesJsonWritten(project)
|
|
}
|
|
|
|
rule RemoveCategory {
|
|
when: RemoveCategoryRequested(project, name)
|
|
ensures: project.metadata.categories = project.metadata.categories - {name}
|
|
ensures: CategorySettingsRemoved(project, name)
|
|
ensures: CategoriesJsonWritten(project)
|
|
ensures: CategoryMetaJsonWritten(project)
|
|
}
|
|
|
|
rule UpdateCategorySettings {
|
|
when: UpdateCategorySettingsRequested(project, category, settings)
|
|
ensures: CategorySettingsUpdated(project, category, settings)
|
|
ensures: CategoryMetaJsonWritten(project)
|
|
}
|
|
|
|
rule SetPublishingPreferences {
|
|
when: SetPublishingPreferencesRequested(project, prefs)
|
|
ensures: project.publishing_preferences = prefs
|
|
ensures: PublishingJsonWritten(project)
|
|
}
|
|
|
|
rule StartupSync {
|
|
when: AppStarted(project)
|
|
-- Loads metadata from filesystem, merges with DB,
|
|
-- creates defaults for new projects
|
|
ensures: ProjectMetadata.synced_from_filesystem(project)
|
|
}
|