rialo_feature_management_interface/lib.rs
1// Copyright (c) Subzero Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Feature Management Program Interface
5//!
6//! This program provides a system-level mechanism for managing feature flags
7//! with time-based activation and deactivation schedules.
8
9#![no_std]
10
11extern crate alloc;
12
13use alloc::vec::Vec;
14
15use rialo_s_pubkey::Pubkey;
16
17pub mod error;
18pub mod features;
19pub mod instruction;
20pub mod state;
21
22rialo_s_pubkey::declare_id!("Feature1111111111111111111111111111111111111");
23
24/// Storage account PDA seed for the features map
25pub const STORAGE_ACCOUNT_SEED: &[u8] = b"features_storage";
26
27/// Derive the storage account address
28pub fn get_storage_account_address() -> (rialo_s_pubkey::Pubkey, u8) {
29 rialo_s_pubkey::Pubkey::find_program_address(&[STORAGE_ACCOUNT_SEED], &id())
30}
31
32/// Maximum length for a feature name
33pub const MAX_FEATURE_NAME_LENGTH: usize = 512;
34
35/// Maximum number of features allowed in the system
36pub const MAX_FEATURE_COUNT: usize = 10000;
37
38/// Maximum number of names a single `Enable` instruction may carry.
39///
40/// Bounded by the ~64 KB transaction-size limit: 100 × 512-byte names
41/// (`MAX_FEATURE_NAME_LENGTH`) plus borsh length prefixes ≈ 51.6 KB, well
42/// inside the envelope with comfortable room for transaction headers,
43/// signatures, and other instructions in the same tx. Raising the cap
44/// requires re-validating the worst-case payload against the tx-size limit.
45pub const MAX_NAMES_PER_BATCH: usize = 100;
46
47/// Maximum total size of serialized features state (100 KB)
48pub const MAX_FEATURES_STATE_SIZE: usize = 100 * 1024;
49
50/// Validates a feature name
51///
52/// Feature names must:
53/// - Not be empty
54/// - Not exceed MAX_FEATURE_NAME_LENGTH
55/// - Contain only alphanumeric characters, underscores, and hyphens
56/// - Not start or end with whitespace
57pub fn validate_feature_name(name: &str) -> bool {
58 !name.is_empty()
59 && name.len() <= MAX_FEATURE_NAME_LENGTH
60 && name
61 .chars()
62 .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
63 && !name.starts_with(char::is_whitespace)
64 && !name.ends_with(char::is_whitespace)
65}
66
67/// Create genesis storage data with initial authority
68///
69/// Creates the initial FeaturesState with the provided authority and serializes it
70/// for use in genesis configuration.
71///
72/// # Arguments
73/// * `authority` - The pubkey that will have authority over the feature management system
74///
75/// # Returns
76/// A `Vec<u8>` containing the serialized FeaturesState
77pub fn genesis_storage(authority: Pubkey) -> Vec<u8> {
78 use state::FeaturesState;
79
80 let state = FeaturesState::new(authority);
81 state
82 .serialize()
83 .expect("Failed to serialize genesis state")
84}