diff --git a/packages/forum_forge/seed/scripts/permissions.lua b/packages/forum_forge/seed/scripts/permissions.lua index 35598eaed..7128296af 100644 --- a/packages/forum_forge/seed/scripts/permissions.lua +++ b/packages/forum_forge/seed/scripts/permissions.lua @@ -1,6 +1,10 @@ --- Permissions facade for forum_forge --- Re-exports single-function modules for backward compatibility +---@module permissions +---@class PermissionsModule +---@field can_post fun(user_id: string, forum_id: string): boolean Check if user can post +---@field can_moderate fun(user_id: string, forum_id: string): boolean Check if user can moderate local M = {} M.can_post = require("can_post") diff --git a/packages/forum_forge/seed/scripts/thread_rank.lua b/packages/forum_forge/seed/scripts/thread_rank.lua index acf5c8519..409ed8b99 100644 --- a/packages/forum_forge/seed/scripts/thread_rank.lua +++ b/packages/forum_forge/seed/scripts/thread_rank.lua @@ -1,6 +1,9 @@ --- Thread ranking facade for forum_forge --- Re-exports single-function modules for backward compatibility +---@module thread_rank +---@class ThreadRankModule +---@field rank_thread fun(thread: Thread): number Calculate thread rank score local M = {} M.rank_thread = require("rank_thread") diff --git a/packages/lua_test/seed/scripts/matchers/collections.lua b/packages/lua_test/seed/scripts/matchers/collections.lua new file mode 100644 index 000000000..03627e5cc --- /dev/null +++ b/packages/lua_test/seed/scripts/matchers/collections.lua @@ -0,0 +1,88 @@ +-- Collection matcher implementations (arrays, strings, tables) +local utils = require("assert_utils") + +---@class CollectionMatchers +local M = {} + +---toContain - for strings and tables +---@param actual any The actual value +---@param expected any The expected value to find +---@param negated boolean Whether assertion is negated +function M.toContain(actual, expected, negated) + local pass = false + + if type(actual) == "string" and type(expected) == "string" then + pass = string.find(actual, expected, 1, true) ~= nil + elseif type(actual) == "table" then + for _, v in pairs(actual) do + if utils.deepEqual(v, expected) then + pass = true + break + end + end + end + + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected " .. utils.stringify(actual) .. " not to contain " .. utils.stringify(expected) + or "Expected " .. utils.stringify(actual) .. " to contain " .. utils.stringify(expected) + error(utils.assertionError(msg, expected, actual)) + end + return true +end + +---toHaveLength +---@param actual any The actual value +---@param expectedLength number The expected length +---@param negated boolean Whether assertion is negated +function M.toHaveLength(actual, expectedLength, negated) + local actualLength + if type(actual) == "string" then + actualLength = #actual + elseif type(actual) == "table" then + actualLength = #actual + else + error("toHaveLength can only be used with strings or tables") + end + + local pass = actualLength == expectedLength + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected length not to be " .. expectedLength .. ", got " .. actualLength + or "Expected length to be " .. expectedLength .. ", got " .. actualLength + error(utils.assertionError(msg, expectedLength, actualLength)) + end + return true +end + +---toHaveProperty +---@param actual any The actual value +---@param key any The property key +---@param value any Optional expected value +---@param negated boolean Whether assertion is negated +function M.toHaveProperty(actual, key, value, negated) + if type(actual) ~= "table" then + error("toHaveProperty can only be used with tables") + end + + local pass = actual[key] ~= nil + if pass and value ~= nil then + pass = utils.deepEqual(actual[key], value) + end + + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected table not to have property " .. utils.stringify(key) + or "Expected table to have property " .. utils.stringify(key) .. (value and " with value " .. utils.stringify(value) or "") + error(utils.assertionError(msg, value, actual[key])) + end + return true +end + +return M diff --git a/packages/lua_test/seed/scripts/matchers/numbers.lua b/packages/lua_test/seed/scripts/matchers/numbers.lua new file mode 100644 index 000000000..9a346a7d7 --- /dev/null +++ b/packages/lua_test/seed/scripts/matchers/numbers.lua @@ -0,0 +1,61 @@ +-- Numeric comparison matcher implementations +local utils = require("assert_utils") + +---@class NumberMatchers +local M = {} + +---toBeGreaterThan +---@param actual any The actual value +---@param expected number The expected value +---@param negated boolean Whether assertion is negated +function M.toBeGreaterThan(actual, expected, negated) + local pass = actual > expected + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected " .. utils.stringify(actual) .. " not to be greater than " .. utils.stringify(expected) + or "Expected " .. utils.stringify(actual) .. " to be greater than " .. utils.stringify(expected) + error(utils.assertionError(msg, "> " .. expected, actual)) + end + return true +end + +---toBeLessThan +---@param actual any The actual value +---@param expected number The expected value +---@param negated boolean Whether assertion is negated +function M.toBeLessThan(actual, expected, negated) + local pass = actual < expected + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected " .. utils.stringify(actual) .. " not to be less than " .. utils.stringify(expected) + or "Expected " .. utils.stringify(actual) .. " to be less than " .. utils.stringify(expected) + error(utils.assertionError(msg, "< " .. expected, actual)) + end + return true +end + +---toBeCloseTo - for floating point comparison +---@param actual any The actual value +---@param expected number The expected value +---@param precision number Decimal precision (default 2) +---@param negated boolean Whether assertion is negated +function M.toBeCloseTo(actual, expected, precision, negated) + precision = precision or 2 + local diff = math.abs(actual - expected) + local pass = diff < (10 ^ -precision) / 2 + if negated then pass = not pass end + + if not pass then + local msg = negated + and "Expected " .. actual .. " not to be close to " .. expected + or "Expected " .. actual .. " to be close to " .. expected .. " (diff: " .. diff .. ")" + error(utils.assertionError(msg, expected, actual)) + end + return true +end + +return M diff --git a/packages/role_editor/seed/scripts/init.lua b/packages/role_editor/seed/scripts/init.lua index b827ed0ca..0400b2b7d 100644 --- a/packages/role_editor/seed/scripts/init.lua +++ b/packages/role_editor/seed/scripts/init.lua @@ -1,6 +1,10 @@ --- Role Editor Package --- Provides configurable role management UI components +--- Role Editor Package +--- Provides configurable role management UI components +---@module init +---@class RoleEditorModule +---@field role table Role management functions +---@field config table Configuration utilities return { role = require("role"), config = require("config") diff --git a/packages/shared/seed/scripts/permissions/README.md b/packages/shared/seed/scripts/permissions/README.md new file mode 100644 index 000000000..49bd21d3c --- /dev/null +++ b/packages/shared/seed/scripts/permissions/README.md @@ -0,0 +1,166 @@ +# Permissions Module + +Fine-grained access control system for MetaBuilder packages and components. + +## Quick Start + +```lua +local permissions = require("permissions") + +-- Initialize system +permissions.initialize_flags({beta_mode = true}) +permissions.enable_database() + +-- Check package access +local result = permissions.check_package_access(4, { + enabled = true, + minLevel = 3, + databaseRequired = true +}) + +if result.allowed then + print("Access granted") +else + print("Denied: " .. result.reason) +end +``` + +## Module Structure + +``` +permissions/ +├── init.lua # Main module facade +├── types.lua # Type definitions +├── check_access.lua # Access checking logic +├── enforce_level.lua # Level enforcement +├── manage_flags.lua # Feature flag management +├── database_toggle.lua # Database control +└── tests/ + ├── check_access.test.lua + ├── manage_flags.test.lua + ├── database_toggle.test.lua + └── integration.test.lua +``` + +## API + +### Access Control + +```lua +-- Check access with full context +permissions.check_access(userLevel, perms, flags?, dbEnabled?) + +-- Check package access (uses current system state) +permissions.check_package_access(userLevel, packagePerms) + +-- Check component access (uses current system state) +permissions.check_component_access(userLevel, componentPerms) + +-- Enforce level (throws on failure) +permissions.enforce_level(userLevel, minLevel, resourceName?) +``` + +### Feature Flags + +```lua +permissions.initialize_flags(flags) +permissions.enable_flag(name) +permissions.disable_flag(name) +permissions.is_flag_enabled(name) +permissions.get_all_flags() +permissions.check_required_flags(required) +``` + +### Database Control + +```lua +permissions.initialize_database(enabled?) +permissions.enable_database() +permissions.disable_database() +permissions.is_database_enabled() +permissions.require_database(resourceName?) +permissions.get_database_status() +``` + +## Permission Levels + +- 0, 1: PUBLIC (no auth) +- 2: USER +- 3: MODERATOR +- 4: ADMIN +- 5: GOD +- 6: SUPERGOD + +## Examples + +### Basic Package Check + +```lua +local packagePerms = { + enabled = true, + minLevel = 3, + databaseRequired = true +} + +local result = permissions.check_package_access(4, packagePerms) +-- result.allowed = true (user level 4 >= required level 3) +``` + +### Component with Feature Flags + +```lua +permissions.enable_flag("beta_ui") + +local componentPerms = { + enabled = true, + minLevel = 2, + featureFlags = {"beta_ui"} +} + +local result = permissions.check_component_access(3, componentPerms) +-- result.allowed = true (level OK, flag enabled) +``` + +### Database Toggle + +```lua +permissions.disable_database() + +local result = permissions.check_package_access(5, { + enabled = true, + minLevel = 2, + databaseRequired = true +}) + +-- result.allowed = false +-- result.reason = "Database is required but not enabled" +``` + +## Testing + +Run tests with your Lua test framework: + +```bash +lua test permissions/tests/check_access.test.lua +lua test permissions/tests/manage_flags.test.lua +lua test permissions/tests/database_toggle.test.lua +lua test permissions/tests/integration.test.lua +``` + +## Type Definitions + +All types are documented with LuaCATS annotations: + +- `PermissionLevel`: 0-6 integer +- `PackagePermissions`: Package permission config +- `ComponentPermission`: Component permission config +- `PermissionCheckResult`: Access check result +- `FeatureFlagState`: Flag state + +See `types.lua` and `shared/scripts/types.lua` for full definitions. + +## See Also + +- [Full Permission System Guide](../../PERMISSIONS_GUIDE.md) +- Package metadata schema +- Renderer integration guide diff --git a/packages/smtp_config/seed/scripts/init.lua b/packages/smtp_config/seed/scripts/init.lua index b34e24c92..3ea4c29a9 100644 --- a/packages/smtp_config/seed/scripts/init.lua +++ b/packages/smtp_config/seed/scripts/init.lua @@ -1,6 +1,10 @@ --- SMTP Config Package --- Provides configurable SMTP configuration UI components +--- SMTP Config Package +--- Provides configurable SMTP configuration UI components +---@module init +---@class SMTPConfigModule +---@field smtp table SMTP configuration functions +---@field validate table Validation utilities return { smtp = require("smtp"), validate = require("validate") diff --git a/packages/social_hub/seed/scripts/composer.lua b/packages/social_hub/seed/scripts/composer.lua index 7a28f61d7..5b3753e50 100644 --- a/packages/social_hub/seed/scripts/composer.lua +++ b/packages/social_hub/seed/scripts/composer.lua @@ -1,6 +1,11 @@ --- Composer component facade for social hub --- Re-exports single-function modules for backward compatibility +---@module composer +---@class ComposerModule +---@field render fun(state: table): string Render composer UI +---@field validate fun(content: string): boolean, string[] Validate post content +---@field submit fun(post: table): boolean, string Submit new post local M = {} M.render = require("render_composer")