2025-03-15 11:00:36 +00:00
|
|
|
<?php
|
|
|
|
|
|
2026-05-12 08:09:18 +00:00
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\InsightCTAMethod;
|
|
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\InsightCTAService;
|
|
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\InsightSeverity;
|
|
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\InsightStatus;
|
|
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\InsightType;
|
|
|
|
|
use Appwrite\Platform\Modules\Advisor\Enums\ReportType;
|
2025-03-17 10:53:09 +00:00
|
|
|
use Appwrite\Platform\Modules\Compute\Specification;
|
2026-04-20 03:24:31 +00:00
|
|
|
use Utopia\System\System;
|
2025-03-15 11:34:49 +00:00
|
|
|
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_NAME = 'Appwrite';
|
|
|
|
|
const APP_DOMAIN = 'appwrite.io';
|
2025-12-07 20:29:45 +00:00
|
|
|
|
2026-02-10 15:51:48 +00:00
|
|
|
const APP_VIEWS_DIR = __DIR__ . '/../views';
|
2026-02-26 05:48:29 +00:00
|
|
|
const APP_CE_CONFIG_DIR = __DIR__ . '/../config';
|
2026-02-10 15:51:48 +00:00
|
|
|
|
2025-12-07 20:29:45 +00:00
|
|
|
// Email
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
|
|
|
|
|
const APP_EMAIL_SECURITY = ''; // Default security email address
|
2025-05-12 13:10:58 +00:00
|
|
|
const APP_EMAIL_LOGO_URL = 'https://cloud.appwrite.io/images/mails/logo.png';
|
2025-05-15 07:44:14 +00:00
|
|
|
const APP_EMAIL_ACCENT_COLOR = '#fd366e';
|
2025-05-12 13:20:59 +00:00
|
|
|
const APP_EMAIL_TERMS_URL = 'https://appwrite.io/terms';
|
|
|
|
|
const APP_EMAIL_PRIVACY_URL = 'https://appwrite.io/privacy';
|
2025-12-07 20:29:45 +00:00
|
|
|
const APP_EMAIL_PLATFORM_NAME = 'Appwrite';
|
|
|
|
|
const APP_EMAIL_FOOTER_IMAGE_URL = 'https://appwrite.io/email/footer.png';
|
|
|
|
|
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s';
|
|
|
|
|
const APP_MODE_DEFAULT = 'default';
|
|
|
|
|
const APP_MODE_ADMIN = 'admin';
|
|
|
|
|
const APP_PAGING_LIMIT = 12;
|
|
|
|
|
const APP_LIMIT_COUNT = 5000;
|
|
|
|
|
const APP_LIMIT_USERS = 10_000;
|
|
|
|
|
const APP_LIMIT_ANTIVIRUS = 20_000_000; //20MB
|
|
|
|
|
const APP_LIMIT_ENCRYPTION = 20_000_000; //20MB
|
|
|
|
|
const APP_LIMIT_COMPRESSION = 20_000_000; //20MB
|
|
|
|
|
const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value
|
|
|
|
|
const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value
|
|
|
|
|
const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length.
|
|
|
|
|
const APP_LIMIT_SUBQUERY = 1000;
|
|
|
|
|
const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
|
|
|
|
|
const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period
|
|
|
|
|
const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds
|
|
|
|
|
const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls
|
2025-04-30 00:09:02 +00:00
|
|
|
const APP_LIMIT_DATABASE_BATCH = 100; // Default maximum batch size for database operations
|
2025-08-14 10:06:43 +00:00
|
|
|
const APP_LIMIT_DATABASE_TRANSACTION = 100; // Default maximum operations per transaction
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours
|
|
|
|
|
const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours
|
|
|
|
|
const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours
|
2025-04-24 05:38:56 +00:00
|
|
|
const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours
|
2025-03-15 12:18:34 +00:00
|
|
|
const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
2026-05-12 11:23:47 +00:00
|
|
|
const APP_CACHE_BUSTER = 4326;
|
2026-05-11 10:53:01 +00:00
|
|
|
const APP_VERSION_STABLE = '1.9.5';
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_DATETIME = 'datetime';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_URL = 'url';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_INT_RANGE = 'intRange';
|
2026-03-30 13:29:24 +00:00
|
|
|
const APP_DATABASE_ATTRIBUTE_BIGINT_RANGE = 'bigintRange';
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_DATABASE_ATTRIBUTE_FLOAT_RANGE = 'floatRange';
|
2025-08-22 07:17:00 +00:00
|
|
|
const APP_DATABASE_ATTRIBUTE_POINT = 'point';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_LINE = 'line';
|
|
|
|
|
const APP_DATABASE_ATTRIBUTE_POLYGON = 'polygon';
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH = 1_073_741_824; // 2^32 bits / 4 bits per char
|
2025-03-15 12:18:34 +00:00
|
|
|
const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds
|
|
|
|
|
const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes
|
|
|
|
|
const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes
|
|
|
|
|
const APP_DATABASE_QUERY_MAX_VALUES = 500;
|
2025-12-17 07:32:59 +00:00
|
|
|
const APP_DATABASE_QUERY_MAX_VALUES_WORKER = 5000;
|
2025-05-23 15:27:35 +00:00
|
|
|
const APP_DATABASE_ENCRYPT_SIZE_MIN = 150;
|
2025-06-17 20:45:07 +00:00
|
|
|
const APP_DATABASE_TXN_TTL_MIN = 60; // 1 minute
|
|
|
|
|
const APP_DATABASE_TXN_TTL_MAX = 3600; // 1 hour
|
|
|
|
|
const APP_DATABASE_TXN_TTL_DEFAULT = 300; // 5 minutes
|
2025-09-03 11:54:21 +00:00
|
|
|
const APP_DATABASE_TXN_MAX_OPERATIONS = 100; // Maximum operations per transaction
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_STORAGE_UPLOADS = '/storage/uploads';
|
2025-03-17 10:53:09 +00:00
|
|
|
const APP_STORAGE_SITES = '/storage/sites';
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_STORAGE_FUNCTIONS = '/storage/functions';
|
|
|
|
|
const APP_STORAGE_BUILDS = '/storage/builds';
|
|
|
|
|
const APP_STORAGE_CACHE = '/storage/cache';
|
2025-04-16 06:26:40 +00:00
|
|
|
const APP_STORAGE_IMPORTS = '/storage/imports'; // Temporary storage for csv imports
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
|
|
|
|
|
const APP_STORAGE_CONFIG = '/storage/config';
|
|
|
|
|
const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT`
|
|
|
|
|
const APP_SOCIAL_TWITTER = 'https://twitter.com/appwrite';
|
|
|
|
|
const APP_SOCIAL_TWITTER_HANDLE = 'appwrite';
|
|
|
|
|
const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
|
|
|
|
|
const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite';
|
|
|
|
|
const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io';
|
|
|
|
|
const APP_SOCIAL_GITHUB = 'https://github.com/appwrite';
|
2025-05-12 13:20:59 +00:00
|
|
|
const APP_SOCIAL_GITHUB_APPWRITE = 'https://github.com/appwrite/appwrite';
|
2025-03-15 11:00:36 +00:00
|
|
|
const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
|
|
|
|
|
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
|
|
|
|
|
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
|
|
|
|
|
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
|
|
|
|
|
const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1';
|
2025-03-17 10:53:09 +00:00
|
|
|
const APP_COMPUTE_CPUS_DEFAULT = 0.5;
|
|
|
|
|
const APP_COMPUTE_MEMORY_DEFAULT = 512;
|
|
|
|
|
const APP_COMPUTE_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB;
|
2026-03-04 13:31:27 +00:00
|
|
|
const APP_COMPUTE_DEPLOYMENT_MAX_RETENTION = 100 * 365; // 100 years
|
2025-12-13 16:06:44 +00:00
|
|
|
const APP_SDK_PLATFORM_SERVER = 'server';
|
|
|
|
|
const APP_SDK_PLATFORM_CLIENT = 'client';
|
|
|
|
|
const APP_SDK_PLATFORM_CONSOLE = 'console';
|
2026-03-28 11:54:20 +00:00
|
|
|
const APP_SDK_PLATFORM_STATIC = 'static';
|
2025-07-22 15:09:36 +00:00
|
|
|
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
|
|
|
|
|
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
|
2025-09-22 14:59:25 +00:00
|
|
|
const APP_VCS_GITHUB_URL = 'https://github.com/TeamAppwrite';
|
2025-10-06 16:22:18 +00:00
|
|
|
const APP_BRANDED_EMAIL_BASE_TEMPLATE = 'email-base-styled';
|
2025-03-15 11:00:36 +00:00
|
|
|
|
2025-11-27 14:32:39 +00:00
|
|
|
/**
|
|
|
|
|
* JWT for Resource Tokens.
|
|
|
|
|
*/
|
|
|
|
|
const RESOURCE_TOKEN_ALGORITHM = 'HS256';
|
|
|
|
|
const RESOURCE_TOKEN_MAX_AGE = 86400 * 365 * 10; /* 10 years */
|
|
|
|
|
const RESOURCE_TOKEN_LEEWAY = 10; // 10 seconds
|
|
|
|
|
|
2025-11-04 06:08:35 +00:00
|
|
|
/**
|
|
|
|
|
* Token Expiration times.
|
|
|
|
|
*/
|
|
|
|
|
const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */
|
|
|
|
|
const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */
|
|
|
|
|
const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */
|
|
|
|
|
const TOKEN_EXPIRATION_CONFIRM = 3600 * 1; /* 1 hour */
|
|
|
|
|
const TOKEN_EXPIRATION_OTP = 60 * 15; /* 15 minutes */
|
|
|
|
|
const TOKEN_EXPIRATION_GENERIC = 60 * 15; /* 15 minutes */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Token Lengths.
|
|
|
|
|
*/
|
|
|
|
|
const TOKEN_LENGTH_MAGIC_URL = 64;
|
|
|
|
|
const TOKEN_LENGTH_VERIFICATION = 256;
|
|
|
|
|
const TOKEN_LENGTH_RECOVERY = 256;
|
|
|
|
|
const TOKEN_LENGTH_OAUTH2 = 64;
|
|
|
|
|
const TOKEN_LENGTH_SESSION = 256;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Token Types.
|
|
|
|
|
*/
|
|
|
|
|
const TOKEN_TYPE_LOGIN = 1; // Deprecated
|
|
|
|
|
const TOKEN_TYPE_VERIFICATION = 2;
|
|
|
|
|
const TOKEN_TYPE_RECOVERY = 3;
|
|
|
|
|
const TOKEN_TYPE_INVITE = 4;
|
|
|
|
|
const TOKEN_TYPE_MAGIC_URL = 5;
|
|
|
|
|
const TOKEN_TYPE_PHONE = 6;
|
|
|
|
|
const TOKEN_TYPE_OAUTH2 = 7;
|
|
|
|
|
const TOKEN_TYPE_GENERIC = 8;
|
|
|
|
|
const TOKEN_TYPE_EMAIL = 9; // OTP
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Session Providers.
|
|
|
|
|
*/
|
|
|
|
|
const SESSION_PROVIDER_EMAIL = 'email';
|
|
|
|
|
const SESSION_PROVIDER_ANONYMOUS = 'anonymous';
|
|
|
|
|
const SESSION_PROVIDER_MAGIC_URL = 'magic-url';
|
|
|
|
|
const SESSION_PROVIDER_PHONE = 'phone';
|
|
|
|
|
const SESSION_PROVIDER_OAUTH2 = 'oauth2';
|
|
|
|
|
const SESSION_PROVIDER_TOKEN = 'token';
|
|
|
|
|
const SESSION_PROVIDER_SERVER = 'server';
|
|
|
|
|
|
|
|
|
|
/**
|
2026-05-18 03:27:34 +00:00
|
|
|
* Actor that performed the request (user, admin, guest, or API key).
|
2025-11-04 06:08:35 +00:00
|
|
|
*/
|
2026-05-18 03:27:34 +00:00
|
|
|
const ACTOR_TYPE_USER = 'user';
|
|
|
|
|
const ACTOR_TYPE_ADMIN = 'admin';
|
|
|
|
|
const ACTOR_TYPE_GUEST = 'guest';
|
|
|
|
|
const ACTOR_TYPE_KEY_PROJECT = 'keyProject';
|
|
|
|
|
const ACTOR_TYPE_KEY_ACCOUNT = 'keyAccount';
|
|
|
|
|
const ACTOR_TYPE_KEY_ORGANIZATION = 'keyOrganization';
|
2025-11-04 06:08:35 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* MFA
|
|
|
|
|
*/
|
|
|
|
|
const MFA_RECENT_DURATION = 1800; // 30 mins
|
|
|
|
|
|
|
|
|
|
|
2026-01-15 05:43:28 +00:00
|
|
|
// Database name
|
|
|
|
|
const APP_DATABASE = 'appwrite';
|
|
|
|
|
|
2025-03-15 11:00:36 +00:00
|
|
|
// Database Reconnect
|
|
|
|
|
const DATABASE_RECONNECT_SLEEP = 2;
|
|
|
|
|
const DATABASE_RECONNECT_MAX_ATTEMPTS = 10;
|
|
|
|
|
|
|
|
|
|
// Database Worker Types
|
|
|
|
|
const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute';
|
|
|
|
|
const DATABASE_TYPE_CREATE_INDEX = 'createIndex';
|
|
|
|
|
const DATABASE_TYPE_DELETE_ATTRIBUTE = 'deleteAttribute';
|
|
|
|
|
const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex';
|
|
|
|
|
const DATABASE_TYPE_DELETE_COLLECTION = 'deleteCollection';
|
|
|
|
|
const DATABASE_TYPE_DELETE_DATABASE = 'deleteDatabase';
|
|
|
|
|
|
|
|
|
|
// Build Worker Types
|
|
|
|
|
const BUILD_TYPE_DEPLOYMENT = 'deployment';
|
|
|
|
|
const BUILD_TYPE_RETRY = 'retry';
|
|
|
|
|
|
|
|
|
|
// Deletion Types
|
2025-08-14 12:32:03 +00:00
|
|
|
|
2026-04-20 03:24:31 +00:00
|
|
|
\define('ENABLE_EXECUTIONS_LIMIT_ON_ROUTE', System::getEnv('_APP_EXECUTIONS_LIMIT_ON_ROUTE', 'disabled') === 'enabled');
|
2026-01-16 10:41:38 +00:00
|
|
|
|
|
|
|
|
const DELETE_TYPE_DATABASES = 'databases';
|
2025-03-15 11:00:36 +00:00
|
|
|
const DELETE_TYPE_DOCUMENT = 'document';
|
|
|
|
|
const DELETE_TYPE_COLLECTIONS = 'collections';
|
2026-05-14 01:58:40 +00:00
|
|
|
const DELETE_TYPE_TRANSACTIONS = 'transactions';
|
2025-09-02 13:31:53 +00:00
|
|
|
const DELETE_TYPE_EXPIRED_TRANSACTIONS = 'expired_transactions';
|
2025-03-15 11:00:36 +00:00
|
|
|
const DELETE_TYPE_PROJECTS = 'projects';
|
2025-03-17 10:53:09 +00:00
|
|
|
const DELETE_TYPE_SITES = 'sites';
|
2025-03-15 11:00:36 +00:00
|
|
|
const DELETE_TYPE_FUNCTIONS = 'functions';
|
|
|
|
|
const DELETE_TYPE_DEPLOYMENTS = 'deployments';
|
|
|
|
|
const DELETE_TYPE_USERS = 'users';
|
2025-12-29 08:04:47 +00:00
|
|
|
const DELETE_TYPE_TEAMS = 'teams';
|
2025-03-15 11:00:36 +00:00
|
|
|
const DELETE_TYPE_TEAM_PROJECTS = 'teams_projects';
|
|
|
|
|
const DELETE_TYPE_EXECUTIONS = 'executions';
|
2026-01-16 09:36:35 +00:00
|
|
|
const DELETE_TYPE_EXECUTIONS_LIMIT = 'executionsLimit';
|
2025-03-15 11:00:36 +00:00
|
|
|
const DELETE_TYPE_AUDIT = 'audit';
|
|
|
|
|
const DELETE_TYPE_ABUSE = 'abuse';
|
|
|
|
|
const DELETE_TYPE_USAGE = 'usage';
|
|
|
|
|
const DELETE_TYPE_REALTIME = 'realtime';
|
|
|
|
|
const DELETE_TYPE_BUCKETS = 'buckets';
|
|
|
|
|
const DELETE_TYPE_INSTALLATIONS = 'installations';
|
|
|
|
|
const DELETE_TYPE_RULES = 'rules';
|
|
|
|
|
const DELETE_TYPE_SESSIONS = 'sessions';
|
|
|
|
|
const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp';
|
|
|
|
|
const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource';
|
|
|
|
|
const DELETE_TYPE_SCHEDULES = 'schedules';
|
|
|
|
|
const DELETE_TYPE_TOPIC = 'topic';
|
|
|
|
|
const DELETE_TYPE_TARGET = 'target';
|
|
|
|
|
const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets';
|
|
|
|
|
const DELETE_TYPE_SESSION_TARGETS = 'session_targets';
|
2025-11-14 02:55:41 +00:00
|
|
|
const DELETE_TYPE_CSV_EXPORTS = 'csv_exports';
|
2025-03-15 12:18:34 +00:00
|
|
|
const DELETE_TYPE_MAINTENANCE = 'maintenance';
|
2026-05-08 06:54:49 +00:00
|
|
|
const DELETE_TYPE_REPORT = 'report';
|
2025-03-15 11:00:36 +00:00
|
|
|
|
2025-12-16 05:29:16 +00:00
|
|
|
// Rule statuses
|
|
|
|
|
const RULE_STATUS_CREATED = 'created'; // This is also the status when domain DNS verification fails.
|
|
|
|
|
const RULE_STATUS_CERTIFICATE_GENERATING = 'verifying';
|
|
|
|
|
const RULE_STATUS_CERTIFICATE_GENERATION_FAILED = 'unverified';
|
|
|
|
|
const RULE_STATUS_VERIFIED = 'verified';
|
|
|
|
|
|
2025-03-15 11:00:36 +00:00
|
|
|
// Message types
|
|
|
|
|
const MESSAGE_SEND_TYPE_INTERNAL = 'internal';
|
|
|
|
|
const MESSAGE_SEND_TYPE_EXTERNAL = 'external';
|
|
|
|
|
// Mail Types
|
|
|
|
|
const MAIL_TYPE_VERIFICATION = 'verification';
|
|
|
|
|
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
|
|
|
|
|
const MAIL_TYPE_RECOVERY = 'recovery';
|
|
|
|
|
const MAIL_TYPE_INVITATION = 'invitation';
|
|
|
|
|
const MAIL_TYPE_CERTIFICATE = 'certificate';
|
|
|
|
|
// Auth Types
|
|
|
|
|
const APP_AUTH_TYPE_SESSION = 'Session';
|
|
|
|
|
const APP_AUTH_TYPE_JWT = 'JWT';
|
|
|
|
|
const APP_AUTH_TYPE_KEY = 'Key';
|
|
|
|
|
const APP_AUTH_TYPE_ADMIN = 'Admin';
|
|
|
|
|
// Response related
|
|
|
|
|
const MAX_OUTPUT_CHUNK_SIZE = 10 * 1024 * 1024; // 10MB
|
2026-04-27 13:15:00 +00:00
|
|
|
const APP_LIMIT_UPLOAD_CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
|
2025-08-20 13:23:55 +00:00
|
|
|
const APP_FUNCTION_LOG_LENGTH_LIMIT = 1000000;
|
2025-08-21 07:19:31 +00:00
|
|
|
const APP_FUNCTION_ERROR_LENGTH_LIMIT = 1000000;
|
2025-03-15 11:00:36 +00:00
|
|
|
// Function headers
|
2025-08-26 07:25:51 +00:00
|
|
|
const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host', 'x-appwrite-client-ip'];
|
2025-03-15 11:00:36 +00:00
|
|
|
const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length'];
|
|
|
|
|
// Message types
|
|
|
|
|
const MESSAGE_TYPE_EMAIL = 'email';
|
|
|
|
|
const MESSAGE_TYPE_SMS = 'sms';
|
|
|
|
|
const MESSAGE_TYPE_PUSH = 'push';
|
|
|
|
|
// API key types
|
|
|
|
|
const API_KEY_STANDARD = 'standard';
|
2026-04-28 15:18:06 +00:00
|
|
|
const API_KEY_EPHEMERAL = 'ephemeral';
|
2025-12-23 12:06:19 +00:00
|
|
|
const API_KEY_ORGANIZATION = 'organization';
|
|
|
|
|
const API_KEY_ACCOUNT = 'account';
|
2025-03-15 11:00:36 +00:00
|
|
|
// Usage metrics
|
|
|
|
|
const METRIC_TEAMS = 'teams';
|
|
|
|
|
const METRIC_USERS = 'users';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent';
|
|
|
|
|
const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed';
|
|
|
|
|
const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent';
|
|
|
|
|
const METRIC_WEBHOOK_ID_FAILED = '{webhookInternalId}.webhooks.events.failed';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone';
|
|
|
|
|
const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}';
|
|
|
|
|
const METRIC_MESSAGES = 'messages';
|
|
|
|
|
const METRIC_MESSAGES_SENT = METRIC_MESSAGES . '.sent';
|
|
|
|
|
const METRIC_MESSAGES_FAILED = METRIC_MESSAGES . '.failed';
|
|
|
|
|
const METRIC_MESSAGES_TYPE = METRIC_MESSAGES . '.{type}';
|
|
|
|
|
const METRIC_MESSAGES_TYPE_SENT = METRIC_MESSAGES . '.{type}.sent';
|
|
|
|
|
const METRIC_MESSAGES_TYPE_FAILED = METRIC_MESSAGES . '.{type}.failed';
|
|
|
|
|
const METRIC_MESSAGES_TYPE_PROVIDER = METRIC_MESSAGES . '.{type}.{provider}';
|
|
|
|
|
const METRIC_MESSAGES_TYPE_PROVIDER_SENT = METRIC_MESSAGES . '.{type}.{provider}.sent';
|
|
|
|
|
const METRIC_MESSAGES_TYPE_PROVIDER_FAILED = METRIC_MESSAGES . '.{type}.{provider}.failed';
|
|
|
|
|
const METRIC_SESSIONS = 'sessions';
|
|
|
|
|
const METRIC_DATABASES = 'databases';
|
|
|
|
|
const METRIC_COLLECTIONS = 'collections';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_DATABASES_STORAGE = 'databases.storage';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_DATABASE_ID_STORAGE = '{databaseInternalId}.databases.storage';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_DOCUMENTS = 'documents';
|
|
|
|
|
const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes';
|
2026-03-19 15:00:42 +00:00
|
|
|
|
|
|
|
|
// documentsdb
|
|
|
|
|
const METRIC_DATABASES_DOCUMENTSDB = 'documentsdb.databases';
|
|
|
|
|
const METRIC_COLLECTIONS_DOCUMENTSDB = 'documentsdb.collections';
|
|
|
|
|
const METRIC_DATABASES_STORAGE_DOCUMENTSDB = 'documentsdb.databases.storage';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTIONS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.collections';
|
|
|
|
|
const METRIC_DATABASE_ID_STORAGE_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.storage';
|
|
|
|
|
const METRIC_DOCUMENTS_DOCUMENTSDB = 'documentsdb.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_DOCUMENTS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.{collectionInternalId}.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.{collectionInternalId}.databases.storage';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB = 'documentsdb.databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_READS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB = 'documentsdb.databases.operations.writes';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_WRITES_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.operations.writes';
|
|
|
|
|
|
|
|
|
|
// vectorsdb
|
|
|
|
|
const METRIC_DATABASES_VECTORSDB = 'vectorsdb.databases';
|
|
|
|
|
const METRIC_COLLECTIONS_VECTORSDB = 'vectorsdb.collections';
|
|
|
|
|
const METRIC_DATABASES_STORAGE_VECTORSDB = 'vectorsdb.databases.storage';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTIONS_VECTORSDB = 'vectorsdb.{databaseInternalId}.collections';
|
|
|
|
|
const METRIC_DATABASE_ID_STORAGE_VECTORSDB = 'vectorsdb.{databaseInternalId}.databases.storage';
|
|
|
|
|
const METRIC_DOCUMENTS_VECTORSDB = 'vectorsdb.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_DOCUMENTS_VECTORSDB = 'vectorsdb.{databaseInternalId}.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS_VECTORSDB = 'vectorsdb.{databaseInternalId}.{collectionInternalId}.documents';
|
|
|
|
|
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE_VECTORSDB = 'vectorsdb.{databaseInternalId}.{collectionInternalId}.databases.storage';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_READS_VECTORSDB = 'vectorsdb.databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_READS_VECTORSDB = 'vectorsdb.{databaseInternalId}.databases.operations.reads';
|
|
|
|
|
const METRIC_DATABASES_OPERATIONS_WRITES_VECTORSDB = 'vectorsdb.databases.operations.writes';
|
|
|
|
|
const METRIC_DATABASE_ID_OPERATIONS_WRITES_VECTORSDB = 'vectorsdb.{databaseInternalId}.databases.operations.writes';
|
|
|
|
|
const METRIC_EMBEDDINGS_TEXT = 'embeddings.text';
|
|
|
|
|
const METRIC_EMBEDDINGS_MODEL_TEXT = 'embeddings.text.{embeddingModel}';
|
|
|
|
|
const METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR = 'embeddings.text.totalErrors';
|
|
|
|
|
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_ERROR = 'embeddings.text.{embeddingModel}.totalErrors';
|
|
|
|
|
const METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION = 'embeddings.text.totalDuration';
|
|
|
|
|
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_DURATION = 'embeddings.text.{embeddingModel}.totalDuration';
|
|
|
|
|
const METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS = 'embeddings.text.totalTokens';
|
|
|
|
|
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_TOKENS = 'embeddings.text.{embeddingModel}.totalTokens';
|
|
|
|
|
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_BUCKETS = 'buckets';
|
|
|
|
|
const METRIC_FILES = 'files';
|
|
|
|
|
const METRIC_FILES_STORAGE = 'files.storage';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_FILES_TRANSFORMATIONS = 'files.transformations';
|
|
|
|
|
const METRIC_BUCKET_ID_FILES_TRANSFORMATIONS = '{bucketInternalId}.files.transformations';
|
|
|
|
|
const METRIC_FILES_IMAGES_TRANSFORMED = 'files.imagesTransformed';
|
|
|
|
|
const METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED = '{bucketInternalId}.files.imagesTransformed';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files';
|
|
|
|
|
const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage';
|
2025-03-17 10:53:09 +00:00
|
|
|
const METRIC_SITES = 'sites';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_FUNCTIONS = 'functions';
|
|
|
|
|
const METRIC_DEPLOYMENTS = 'deployments';
|
|
|
|
|
const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage';
|
|
|
|
|
const METRIC_BUILDS = 'builds';
|
|
|
|
|
const METRIC_BUILDS_SUCCESS = 'builds.success';
|
|
|
|
|
const METRIC_BUILDS_FAILED = 'builds.failed';
|
|
|
|
|
const METRIC_BUILDS_STORAGE = 'builds.storage';
|
|
|
|
|
const METRIC_BUILDS_COMPUTE = 'builds.compute';
|
|
|
|
|
const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success';
|
|
|
|
|
const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed';
|
|
|
|
|
const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds';
|
|
|
|
|
const METRIC_EXECUTIONS = 'executions';
|
|
|
|
|
const METRIC_EXECUTIONS_COMPUTE = 'executions.compute';
|
|
|
|
|
const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds';
|
2025-03-31 06:28:58 +00:00
|
|
|
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS = '{resourceType}.{resourceInternalId}.executions';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE = '{resourceType}.{resourceInternalId}.executions.compute';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS = '{resourceType}.{resourceInternalId}.executions.mbSeconds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS = '{resourceType}.{resourceInternalId}.builds.success';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED = '{resourceType}.{resourceInternalId}.builds.failed';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE = '{resourceType}.{resourceInternalId}.builds.compute';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS = '{resourceType}.{resourceInternalId}.builds.compute.success';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED = '{resourceType}.{resourceInternalId}.builds.compute.failed';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS = '{resourceType}.{resourceInternalId}.builds.mbSeconds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
2025-04-01 02:21:52 +00:00
|
|
|
const METRIC_RESOURCE_TYPE_EXECUTIONS = '{resourceType}.executions';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE = '{resourceType}.executions.compute';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS = '{resourceType}.executions.mbSeconds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_SUCCESS = '{resourceType}.builds.success';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_FAILED = '{resourceType}.builds.failed';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE = '{resourceType}.builds.compute';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS = '{resourceType}.builds.compute.success';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED = '{resourceType}.builds.compute.failed';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS = '{resourceType}.builds.mbSeconds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS = '{resourceType}.builds';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_BUILDS_STORAGE = '{resourceType}.builds.storage';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_DEPLOYMENTS = '{resourceType}.deployments';
|
|
|
|
|
const METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE = '{resourceType}.deployments.storage';
|
2025-03-15 11:00:36 +00:00
|
|
|
const METRIC_NETWORK_REQUESTS = 'network.requests';
|
|
|
|
|
const METRIC_NETWORK_INBOUND = 'network.inbound';
|
|
|
|
|
const METRIC_NETWORK_OUTBOUND = 'network.outbound';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_MAU = 'users.mau';
|
|
|
|
|
const METRIC_DAU = 'users.dau';
|
|
|
|
|
const METRIC_WAU = 'users.wau';
|
2026-04-28 11:49:24 +00:00
|
|
|
const METRIC_USERS_PRESENCE = 'users.presence';
|
2025-03-15 12:18:34 +00:00
|
|
|
const METRIC_WEBHOOKS = 'webhooks';
|
|
|
|
|
const METRIC_PLATFORMS = 'platforms';
|
|
|
|
|
const METRIC_PROVIDERS = 'providers';
|
|
|
|
|
const METRIC_TOPICS = 'topics';
|
|
|
|
|
const METRIC_TARGETS = 'targets';
|
|
|
|
|
const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets';
|
|
|
|
|
const METRIC_KEYS = 'keys';
|
2025-03-16 02:35:10 +00:00
|
|
|
const METRIC_DOMAINS = 'domains';
|
2025-04-02 05:10:12 +00:00
|
|
|
const METRIC_SITES_REQUESTS = 'sites.requests';
|
|
|
|
|
const METRIC_SITES_INBOUND = 'sites.inbound';
|
|
|
|
|
const METRIC_SITES_OUTBOUND = 'sites.outbound';
|
2025-04-02 05:15:33 +00:00
|
|
|
const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests';
|
|
|
|
|
const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
|
|
|
|
|
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
|
2025-10-27 06:44:04 +00:00
|
|
|
const METRIC_AVATARS_SCREENSHOTS_GENERATED = 'avatars.screenshotsGenerated';
|
2025-11-09 07:17:40 +00:00
|
|
|
const METRIC_FUNCTIONS_RUNTIME = 'functions.runtimes.{runtime}';
|
|
|
|
|
const METRIC_SITES_FRAMEWORK = 'sites.frameworks.{framework}';
|
2025-03-15 12:18:34 +00:00
|
|
|
|
2026-03-03 13:18:37 +00:00
|
|
|
// Realtime metrics
|
|
|
|
|
const METRIC_REALTIME_CONNECTIONS = 'realtime.connections';
|
|
|
|
|
const METRIC_REALTIME_CONNECTIONS_MESSAGES_SENT = 'realtime.messages.sent';
|
|
|
|
|
const METRIC_REALTIME_INBOUND = 'realtime.inbound';
|
|
|
|
|
const METRIC_REALTIME_OUTBOUND = 'realtime.outbound';
|
|
|
|
|
|
2025-03-15 12:18:34 +00:00
|
|
|
// Resource types
|
|
|
|
|
const RESOURCE_TYPE_PROJECTS = 'projects';
|
|
|
|
|
const RESOURCE_TYPE_FUNCTIONS = 'functions';
|
2025-03-17 10:53:09 +00:00
|
|
|
const RESOURCE_TYPE_SITES = 'sites';
|
2025-03-15 12:18:34 +00:00
|
|
|
const RESOURCE_TYPE_DATABASES = 'databases';
|
|
|
|
|
const RESOURCE_TYPE_BUCKETS = 'buckets';
|
|
|
|
|
const RESOURCE_TYPE_PROVIDERS = 'providers';
|
|
|
|
|
const RESOURCE_TYPE_TOPICS = 'topics';
|
|
|
|
|
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
|
|
|
|
|
const RESOURCE_TYPE_MESSAGES = 'messages';
|
2025-09-23 02:05:17 +00:00
|
|
|
const RESOURCE_TYPE_EXECUTIONS = 'executions';
|
2026-02-04 14:33:52 +00:00
|
|
|
const RESOURCE_TYPE_VCS = 'vcs';
|
2026-03-19 15:00:42 +00:00
|
|
|
const RESOURCE_TYPE_EMBEDDINGS_TEXT = 'embeddingsText';
|
2026-05-01 00:40:28 +00:00
|
|
|
const RESOURCE_TYPE_INSIGHTS = 'insights';
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
const RESOURCE_TYPE_REPORTS = 'reports';
|
2026-05-01 00:40:28 +00:00
|
|
|
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
// Insight types — engine-specific so the CTA action can reference the right public API.
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_INSIGHT_TYPES = [
|
2026-05-12 08:09:18 +00:00
|
|
|
InsightType::DATABASE_INDEX->value, // legacy databases.createIndex
|
|
|
|
|
InsightType::TABLES_DB_INDEX->value, // tablesDB.createIndex
|
|
|
|
|
InsightType::DOCUMENTS_DB_INDEX->value, // documentsDB.createIndex
|
|
|
|
|
InsightType::VECTORS_DB_INDEX->value, // vectorsDB.createIndex
|
|
|
|
|
InsightType::DATABASE_PERFORMANCE->value,
|
|
|
|
|
InsightType::SITE_PERFORMANCE->value,
|
|
|
|
|
InsightType::SITE_ACCESSIBILITY->value,
|
|
|
|
|
InsightType::SITE_SEO->value,
|
|
|
|
|
InsightType::FUNCTION_PERFORMANCE->value,
|
2026-05-01 00:40:28 +00:00
|
|
|
];
|
|
|
|
|
|
2026-05-06 04:35:33 +00:00
|
|
|
// Public API services (SDK namespaces) that an insight CTA's `service` can reference.
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
// Analyzers must pick the one matching the engine the resource lives in.
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_CTA_SERVICES = [
|
2026-05-12 08:09:18 +00:00
|
|
|
InsightCTAService::DATABASES->value, // legacy
|
|
|
|
|
InsightCTAService::TABLES_DB->value,
|
|
|
|
|
InsightCTAService::DOCUMENTS_DB->value,
|
|
|
|
|
InsightCTAService::VECTORS_DB->value,
|
2026-05-11 01:59:31 +00:00
|
|
|
];
|
2026-05-06 04:35:33 +00:00
|
|
|
|
|
|
|
|
// Public API method names that an insight CTA's `method` can reference for index suggestions.
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_CTA_METHODS = [
|
2026-05-12 08:09:18 +00:00
|
|
|
InsightCTAMethod::CREATE_INDEX->value,
|
2026-05-11 01:59:31 +00:00
|
|
|
];
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
|
2026-05-01 00:40:28 +00:00
|
|
|
// Insight severities
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_SEVERITIES = [
|
2026-05-12 08:09:18 +00:00
|
|
|
InsightSeverity::INFO->value,
|
|
|
|
|
InsightSeverity::WARNING->value,
|
|
|
|
|
InsightSeverity::CRITICAL->value,
|
2026-05-01 00:40:28 +00:00
|
|
|
];
|
|
|
|
|
|
2026-05-01 02:36:31 +00:00
|
|
|
// Insight statuses
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_STATUSES = [
|
2026-05-12 08:09:18 +00:00
|
|
|
InsightStatus::ACTIVE->value,
|
|
|
|
|
InsightStatus::DISMISSED->value,
|
2026-05-01 02:36:31 +00:00
|
|
|
];
|
|
|
|
|
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
// Report types
|
2026-05-11 02:08:29 +00:00
|
|
|
const ADVISOR_REPORT_TYPES = [
|
2026-05-12 08:09:18 +00:00
|
|
|
ReportType::LIGHTHOUSE->value,
|
|
|
|
|
ReportType::AUDIT->value,
|
|
|
|
|
ReportType::DATABASE_ANALYZER->value,
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
];
|
2025-04-28 14:31:42 +00:00
|
|
|
|
|
|
|
|
// Resource types for Tokens
|
|
|
|
|
const TOKENS_RESOURCE_TYPE_FILES = 'files';
|
|
|
|
|
const TOKENS_RESOURCE_TYPE_SITES = 'sites';
|
|
|
|
|
const TOKENS_RESOURCE_TYPE_FUNCTIONS = 'functions';
|
|
|
|
|
const TOKENS_RESOURCE_TYPE_DATABASES = 'databases';
|
2025-09-22 08:50:58 +00:00
|
|
|
|
2025-09-22 14:28:18 +00:00
|
|
|
// Resource types for Schedules
|
|
|
|
|
const SCHEDULE_RESOURCE_TYPE_EXECUTION = 'execution';
|
|
|
|
|
const SCHEDULE_RESOURCE_TYPE_FUNCTION = 'function';
|
|
|
|
|
const SCHEDULE_RESOURCE_TYPE_MESSAGE = 'message';
|
2025-11-05 07:09:18 +00:00
|
|
|
|
|
|
|
|
/** Preview cookie */
|
2025-11-05 07:10:47 +00:00
|
|
|
const COOKIE_NAME_PREVIEW = 'a_jwt_console';
|
2026-02-02 12:48:31 +00:00
|
|
|
|
|
|
|
|
// Cache Reconnect
|
2026-02-02 13:19:41 +00:00
|
|
|
const CACHE_RECONNECT_MAX_RETRIES = 2;
|
2026-02-02 12:48:31 +00:00
|
|
|
const CACHE_RECONNECT_RETRY_DELAY = 1000;
|
2026-02-11 01:18:21 +00:00
|
|
|
|
|
|
|
|
// Project status
|
2026-02-11 01:25:04 +00:00
|
|
|
const PROJECT_STATUS_ACTIVE = 'active';
|
2026-03-19 15:00:42 +00:00
|
|
|
|
|
|
|
|
// Database types
|
|
|
|
|
const DATABASE_TYPE_LEGACY = 'legacy';
|
|
|
|
|
const DATABASE_TYPE_TABLESDB = 'tablesdb';
|
|
|
|
|
const DATABASE_TYPE_DOCUMENTSDB = 'documentsdb';
|
|
|
|
|
const DATABASE_TYPE_VECTORSDB = 'vectorsdb';
|
|
|
|
|
|
|
|
|
|
// CSV import/export allowed database types
|
|
|
|
|
const CSV_ALLOWED_DATABASE_TYPES = [
|
|
|
|
|
DATABASE_TYPE_LEGACY,
|
|
|
|
|
DATABASE_TYPE_TABLESDB,
|
|
|
|
|
DATABASE_TYPE_VECTORSDB
|
|
|
|
|
];
|
2026-05-14 12:29:34 +00:00
|
|
|
|
|
|
|
|
const VCS_DEPLOYMENT_SKIP_PATTERNS = [
|
|
|
|
|
'[skip ci]',
|
|
|
|
|
];
|