{ "version": "1.0.0", "runDate": "2026-06-10T07:50:18.876Z", "mode": "without-skills", "totalQuestions": 191, "totalMcq": 165, "totalFreeform": 26, "totalPromptTokens": 1356700, "totalCompletionTokens": 2420071, "totalTokens": 3776771, "totalCost": 17.093201, "totalDurationMs": 42067687, "models": [ { "modelId": "deepseek-v4-flash", "modelName": "DeepSeek V4 Flash", "provider": "DeepSeek", "promptCostPerMillionTokens": 0.1, "completionCostPerMillionTokens": 0.2, "scores": { "foundation": 98.8, "auth": 98, "tablesdb": 88.3, "functions": 90.8, "storage": 95, "sites": 90.5, "messaging": 98.5, "realtime": 95, "cli": 56.1 }, "mcqScores": { "foundation": 100, "auth": 100, "tablesdb": 95, "functions": 94.1, "storage": 94.1, "sites": 94.4, "messaging": 100, "realtime": 100, "cli": 56 }, "freeformScores": { "foundation": 91.7, "auth": 86.7, "tablesdb": 43.3, "functions": 71.7, "storage": 100, "sites": 55, "messaging": 90, "realtime": 66.7, "cli": 56.7 }, "overall": 88.6, "mcqOverall": 90.9, "freeformOverall": 74.2, "totalQuestions": 191, "totalCorrect": 171, "totalPromptTokens": 103492, "totalCompletionTokens": 155207, "totalTokens": 258699, "totalCost": 0.057944, "totalDurationMs": 5063255, "averageTokensPerSecond": 30.65, "runDate": "2026-06-10T07:50:18.872Z", "questionDetails": [ { "questionId": "fund-1", "category": "foundation", "type": "mcq", "question": "What type of platform is Appwrite?", "choices": [ "An open-source backend-as-a-service (BaaS) platform", "A frontend JavaScript framework", "A cloud hosting provider", "A database management system" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 593, "completionTokens": 52, "totalTokens": 645, "cost": 0.000098, "durationMs": 30391, "tokensPerSecond": 1.71, "toolCallCount": 0 }, { "questionId": "fund-2", "category": "foundation", "type": "mcq", "question": "Which of the following is NOT one of Appwrite's core services?", "choices": [ "Auth", "TablesDB", "Container Orchestration", "Storage" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 563, "completionTokens": 257, "totalTokens": 820, "cost": 0.000151, "durationMs": 8580, "tokensPerSecond": 29.95, "toolCallCount": 0 }, { "questionId": "fund-3", "category": "foundation", "type": "mcq", "question": "What API protocols does Appwrite support?", "choices": [ "REST only", "GraphQL only", "REST and GraphQL", "gRPC and REST" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 571, "completionTokens": 96, "totalTokens": 667, "cost": 0.000107, "durationMs": 28022, "tokensPerSecond": 3.43, "toolCallCount": 0 }, { "questionId": "fund-4", "category": "foundation", "type": "mcq", "question": "What is the purpose of an Appwrite API key?", "choices": [ "To encrypt database rows", "To configure DNS settings", "To authenticate server-side requests with specific scope permissions", "To manage SSL certificates" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 588, "completionTokens": 197, "totalTokens": 785, "cost": 0.000137, "durationMs": 4880, "tokensPerSecond": 40.37, "toolCallCount": 0 }, { "questionId": "fund-5", "category": "foundation", "type": "mcq", "question": "Which Appwrite feature enables real-time data synchronization?", "choices": [ "Webhooks", "Server Functions", "Realtime API via WebSocket subscriptions", "Scheduled Tasks" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 571, "completionTokens": 137, "totalTokens": 708, "cost": 0.000118, "durationMs": 51932, "tokensPerSecond": 2.64, "toolCallCount": 0 }, { "questionId": "fund-6", "category": "foundation", "type": "free-form", "question": "Explain the difference between client-side and server-side SDKs in Appwrite. When would you use each?", "correctAnswer": "Client SDKs are designed for frontend applications where end users interact directly. They require active sessions for authentication. Server SDKs are for backend applications and use API keys with configurable scopes, allowing operations that bypass collection-level permissions.", "rubric": "Must mention: 1) Client SDKs for frontend/user-facing apps, 2) Server SDKs use API keys, 3) Server SDKs can bypass permissions, 4) Client SDKs require user sessions", "modelAnswer": "The fundamental difference between Appwrite's client-side and server-side SDKs lies in the **trust boundary** and the **authentication method** used.\n\n### Client-Side SDKs (Web, Flutter, Apple, Android)\n- **Environment:** Untrusted (user's browser or device).\n- **Authentication:** Uses **User Sessions** (email/password, OAuth, magic URLs, JWT tokens). The SDK automatically manages session tokens.\n- **Permissions:** Operations are strictly scoped by the **logged-in user's permissions** and roles. You cannot perform admin-level tasks.\n- **Security:** **Never expose API keys here.** The SDK only needs the Project ID and endpoint.\n\n**Use Client SDKs for:**\n- User authentication (login, signup, logout, password recovery).\n- Fetching data the current user has access to.\n- Uploading files as the current user.\n- Subscribing to realtime events.\n- Executing Cloud Functions on behalf of the user.\n\n---\n\n### Server-Side SDKs (Node.js, Python, PHP, Ruby, Dart, Kotlin, Swift, .NET, Deno)\n- **Environment:** Trusted (your backend server, Cloud Function, cron job).\n- **Authentication:** Uses a **Project API Key** (a secret string). This key is scoped to specific services and has full administrative access.\n- **Permissions:** Bypasses user permissions entirely. The SDK has **full administrative control** over the project.\n- **Security:** Must be kept secret. Never commit it to version control or expose it to the client.\n\n**Use Server SDKs for:**\n- Admin panels and dashboards.\n- Backend logic, cron jobs, and webhooks.\n- Appwrite Cloud Functions.\n- Bulk operations (creating thousands of users or documents).\n- Managing the project structure (creating collections, buckets, functions).\n- Managing users, teams, and memberships programmatically.\n- Server-to-server integrations.\n\n---\n\n### The Golden Rule\n**Never use a Server SDK in a client application.** Exposing your API Key gives an attacker full control over your Appwrite project. Always use the Client SDK for user-facing features and the Server SDK for backend/admin tasks.", "correct": true, "score": 1, "judgeReasoning": "The answer fully covers all four rubric requirements: 1) Client SDKs are for frontend/user-facing apps (browsers, mobile devices), 2) Server SDKs use API keys for authentication, 3) Server SDKs bypass user permissions with full administrative control, and 4) Client SDKs require user sessions. The answer goes well beyond the minimum requirements with detailed explanations of use cases, security considerations, and a clear 'golden rule' summary.", "promptTokens": 133, "completionTokens": 2129, "totalTokens": 2262, "cost": 0.000615, "durationMs": 27959, "tokensPerSecond": 76.15, "toolCallCount": 0 }, { "questionId": "fund-7", "category": "foundation", "type": "mcq", "question": "How is Appwrite typically deployed?", "choices": [ "Using Docker containers", "As a native OS application", "As a browser extension", "Through npm global install" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 574, "completionTokens": 88, "totalTokens": 662, "cost": 0.000105, "durationMs": 2358, "tokensPerSecond": 37.32, "toolCallCount": 0 }, { "questionId": "fund-8", "category": "foundation", "type": "free-form", "question": "Describe how Appwrite's permission model works. What are the different permission types available?", "correctAnswer": "Appwrite uses a flexible permission system where each resource (document, file, etc.) has its own permission list. Permissions use Permission.read/create/update/delete with roles like Role.any(), Role.guests(), Role.users(), Role.user(id), Role.team(id), Role.member(id), Role.label(label).", "rubric": "Must mention: 1) Permission types (read, create, update, delete), 2) At least 3 role types, 3) That permissions are set on resources", "modelAnswer": "Appwrite uses a **role-based access control (RBAC)** model. Permissions are defined as strings that combine an **action** (what you can do) and a **role** (who can do it), formatted as `action:role`.\n\n### Permission Types (Actions)\nThese define the level of access granted:\n\n- **`read`** – Allows viewing the resource.\n- **`create`** – Allows creating a new resource.\n- **`update`** – Allows modifying an existing resource.\n- **`delete`** – Allows removing a resource.\n- **`write`** – A shorthand permission that grants `create`, `update`, and `delete` simultaneously.\n\n### Role Types (Targets)\nThese define who the permission applies to:\n\n- **`any`** – Everyone (authenticated and unauthenticated users).\n- **`guests`** – Only unauthenticated users.\n- **`users`** – Any authenticated user.\n- **`user:{userId}`** – A specific user by their unique ID.\n- **`team:{teamId}/{role}`** – Members of a specific team with a specific role (e.g., `team:abc123/admin`, `team:abc123/member`, or a custom role).\n\n### How It Works in Practice\nPermissions can be applied at two levels:\n\n1. **Collection / Bucket Level** – Default permissions for all documents or files within that resource.\n2. **Document / File Level** – Specific permissions on an individual resource that override the collection/bucket defaults.\n\n**Example:**\nTo make a document publicly readable but only editable by a specific user, you set its permissions to:\n```json\n[\"read:any\", \"write:user:USER_ID\"]\n```\n\nThis granular model gives you full control over data access, from fully public resources to tightly restricted, user-specific documents.", "correct": true, "score": 0.85, "judgeReasoning": "The answer correctly covers all three rubric requirements: 1) Permission types (read, create, update, delete) are mentioned, plus the bonus 'write' shorthand; 2) More than 3 role types are listed (any, guests, users, user:{userId}, team:{teamId}); 3) Permissions being set on resources is explained at both collection/bucket and document/file levels. The answer is largely accurate and well-structured. Minor issues: the permission format shown uses 'action:role' string syntax (e.g., 'read:any') which is an older Appwrite format, while the reference answer uses the newer Permission.read/create/update/delete with Role.* helper methods. Also missing Role.member() and Role.label() from the reference. The core concepts are correct though, warranting a high score with slight deduction for the outdated syntax format and missing some role types.", "promptTokens": 129, "completionTokens": 2581, "totalTokens": 2710, "cost": 0.000741, "durationMs": 28643, "tokensPerSecond": 90.11, "toolCallCount": 0 }, { "questionId": "fund-9", "category": "foundation", "type": "mcq", "question": "What is a \"project\" in Appwrite?", "choices": [ "A single TablesDB table", "A Git repository connection", "An isolated container for your application's backend services and resources", "A deployment environment" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 591, "completionTokens": 85, "totalTokens": 676, "cost": 0.000107, "durationMs": 2353, "tokensPerSecond": 36.12, "toolCallCount": 0 }, { "questionId": "fund-10", "category": "foundation", "type": "mcq", "question": "Which of the following is a valid way to subscribe to Appwrite Realtime events?", "choices": [ "HTTP long polling", "Server-Sent Events (SSE)", "WebSocket subscription using realtime.subscribe()", "GraphQL subscriptions" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 595, "completionTokens": 200, "totalTokens": 795, "cost": 0.000139, "durationMs": 6069, "tokensPerSecond": 32.95, "toolCallCount": 0 }, { "questionId": "fund-11", "category": "foundation", "type": "mcq", "question": "What is required when initializing the Appwrite client in a frontend app?", "choices": [ "Only the API key", "Project ID only", "Endpoint, Project ID, and a secret key", "Endpoint and Project ID at minimum" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 599, "completionTokens": 151, "totalTokens": 750, "cost": 0.000126, "durationMs": 3510, "tokensPerSecond": 43.02, "toolCallCount": 0 }, { "questionId": "fund-12", "category": "foundation", "type": "mcq", "question": "How do Webhooks differ from Realtime in Appwrite?", "choices": [ "Realtime uses WebSockets for live client updates; Webhooks are HTTP callbacks to your server when events occur", "They are the same feature with different names", "Webhooks are for client-side only", "Realtime is server-to-server only" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 637, "completionTokens": 220, "totalTokens": 857, "cost": 0.000151, "durationMs": 23818, "tokensPerSecond": 9.24, "toolCallCount": 0 }, { "questionId": "fund-13", "category": "foundation", "type": "mcq", "question": "What are API key scopes in Appwrite?", "choices": [ "Geographic regions for the key", "Rate limit tiers", "Permissions that limit what the API key can access (e.g. tablesdb.read, users.write)", "Encryption levels" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 605, "completionTokens": 198, "totalTokens": 803, "cost": 0.00014, "durationMs": 23697, "tokensPerSecond": 8.36, "toolCallCount": 0 }, { "questionId": "fund-14", "category": "foundation", "type": "mcq", "question": "Which role allows access to any user (including unauthenticated)?", "choices": [ "Role.any()", "Role.users()", "Role.guests()", "Role.public()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 577, "completionTokens": 1962, "totalTokens": 2539, "cost": 0.00063, "durationMs": 98134, "tokensPerSecond": 19.99, "toolCallCount": 0 }, { "questionId": "fund-15", "category": "foundation", "type": "mcq", "question": "How is Appwrite typically run in production?", "choices": [ "As a single PHP script", "Only on Appwrite Cloud", "Using Docker containers (e.g. docker compose)", "As a serverless deployment" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 592, "completionTokens": 129, "totalTokens": 721, "cost": 0.000119, "durationMs": 6600, "tokensPerSecond": 19.55, "toolCallCount": 0 }, { "questionId": "fund-16", "category": "foundation", "type": "mcq", "question": "What does Role.guests() represent?", "choices": [ "Users who have not verified their email", "Users in a guest team", "Unauthenticated users (no session)", "Anonymous session users only" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 590, "completionTokens": 490, "totalTokens": 1080, "cost": 0.00022, "durationMs": 12881, "tokensPerSecond": 38.04, "toolCallCount": 0 }, { "questionId": "fund-17", "category": "foundation", "type": "mcq", "question": "Can you use both REST and GraphQL in the same Appwrite project?", "choices": [ "Yes, Appwrite supports both REST and GraphQL APIs for the same data", "No, you must choose one", "Only if you use separate projects", "GraphQL is only for the Console" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 618, "completionTokens": 137, "totalTokens": 755, "cost": 0.000125, "durationMs": 3538, "tokensPerSecond": 38.72, "toolCallCount": 0 }, { "questionId": "fund-18", "category": "foundation", "type": "mcq", "question": "Which permission type allows creating a new resource?", "choices": [ "Permission.read()", "Permission.write()", "Permission.create()", "Permission.insert()" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 565, "completionTokens": 301, "totalTokens": 866, "cost": 0.000163, "durationMs": 10017, "tokensPerSecond": 30.05, "toolCallCount": 0 }, { "questionId": "fund-19", "category": "foundation", "type": "mcq", "question": "What is the purpose of adding a platform (e.g. Web app) to an Appwrite project?", "choices": [ "To enable billing for that platform", "To install a plugin", "To register allowed origins/hosts for auth redirects and API access", "To assign a subdomain" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 612, "completionTokens": 188, "totalTokens": 800, "cost": 0.000138, "durationMs": 10147, "tokensPerSecond": 18.53, "toolCallCount": 0 }, { "questionId": "fund-20", "category": "foundation", "type": "free-form", "question": "Name at least three Appwrite services (product areas) and what each is used for.", "correctAnswer": "Examples: Auth (users, sessions, OAuth, MFA, teams), TablesDB (tables, rows, queries, relationships), Storage (buckets, files, previews), Functions (serverless execution), Realtime (WebSocket subscriptions), Messaging (email, SMS, push), Sites (static/dynamic hosting), GraphQL (query API).", "rubric": "Must name at least 3 services with correct purpose. Accept Auth, TablesDB, Storage, Functions, Realtime, Messaging, Sites, GraphQL, CLI, etc. with accurate descriptions.", "modelAnswer": "Here are three core Appwrite services and their primary use cases:\n\n1. **Authentication**: Manages user identity and access control. It handles user registration, login, logout, session management, and supports multiple authentication methods including email/password, OAuth2 providers (Google, GitHub, etc.), magic URLs, and phone authentication.\n\n2. **Databases**: A NoSQL document database service for storing, querying, and managing structured data. It allows you to create collections, define attributes and indexes, perform CRUD operations, set granular permissions, and subscribe to real-time changes.\n\n3. **Functions**: A serverless compute service for running custom backend code. Functions can be triggered via HTTP requests, scheduled cron jobs, or Appwrite events (like a document being created or a user signing up), allowing you to extend your app's logic without managing servers.", "correct": true, "score": 0.9, "judgeReasoning": "The answer correctly identifies three Appwrite services with accurate descriptions: Authentication (user management, sessions, OAuth2), Databases (document storage, collections, CRUD operations), and Functions (serverless execution, HTTP triggers, cron jobs, event triggers). All three descriptions are accurate and detailed. The only minor issue is that 'Databases' is described as NoSQL document database, which reflects the older Appwrite architecture - the newer version uses 'TablesDB' - but the core functionality described is correct. The answer meets the requirement of naming at least 3 services with correct purposes.", "promptTokens": 130, "completionTokens": 1065, "totalTokens": 1195, "cost": 0.000316, "durationMs": 15807, "tokensPerSecond": 67.38, "toolCallCount": 0 }, { "questionId": "auth-1", "category": "auth", "type": "mcq", "question": "Which method creates a new email/password account in Appwrite?", "choices": [ "account.create()", "account.createEmailPasswordSession()", "auth.register()", "users.create()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 575, "completionTokens": 203, "totalTokens": 778, "cost": 0.000137, "durationMs": 5337, "tokensPerSecond": 38.04, "toolCallCount": 0 }, { "questionId": "auth-2", "category": "auth", "type": "mcq", "question": "What is the correct method to create an email/password session (log in) using the Appwrite client SDK?", "choices": [ "account.createEmailPasswordSession()", "account.login()", "auth.signIn()", "account.create()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 587, "completionTokens": 346, "totalTokens": 933, "cost": 0.000179, "durationMs": 12865, "tokensPerSecond": 26.89, "toolCallCount": 0 }, { "questionId": "auth-3", "category": "auth", "type": "mcq", "question": "How does Appwrite handle OAuth2 authentication?", "choices": [ "It only supports OAuth2 through custom functions", "OAuth2 requires a separate plugin installation", "It provides built-in OAuth2 support with createOAuth2Session() for 40+ providers", "It uses JWT tokens exclusively" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 631, "completionTokens": 233, "totalTokens": 864, "cost": 0.000154, "durationMs": 5328, "tokensPerSecond": 43.73, "toolCallCount": 0 }, { "questionId": "auth-4", "category": "auth", "type": "free-form", "question": "Write the code to implement email/password signup and login using the Appwrite Web SDK. Include setting up the client, creating an account, and creating a session.", "correctAnswer": "The Appwrite Web SDK requires initializing a Client with endpoint and project ID, then creating an Account instance. Registration uses account.create(ID.unique(), email, password, name). Login uses account.createEmailPasswordSession(email, password).", "rubric": "Must include: 1) Client initialization with setEndpoint and setProject, 2) Account service instantiation, 3) account.create() with ID.unique(), email, password, 4) account.createEmailPasswordSession(), 5) Correct imports from appwrite", "modelAnswer": "Below is a complete implementation for email/password signup and login using the **Appwrite Web SDK** (v1.x). It includes client setup, account creation, and session creation.\n\n```javascript\n// 1. Import the Appwrite SDK\nimport { Client, Account } from 'appwrite';\n\n// 2. Initialize the Appwrite client\nconst client = new Client()\n .setEndpoint('https://cloud.appwrite.io/v1') // Your Appwrite endpoint\n .setProject('YOUR_PROJECT_ID'); // Your project ID\n\n// 3. Create an Account instance\nconst account = new Account(client);\n\n// 4. Signup function (creates a new user account)\nasync function signup(email, password, name) {\n try {\n const response = await account.create(\n 'unique()', // userId – use 'unique()' to auto-generate\n email,\n password,\n name\n );\n console.log('Account created:', response);\n // Optionally, you can automatically log in after signup\n // await login(email, password);\n return response;\n } catch (error) {\n console.error('Signup error:', error.message);\n throw error;\n }\n}\n\n// 5. Login function (creates an email/password session)\nasync function login(email, password) {\n try {\n const response = await account.createEmailPasswordSession(\n email,\n password\n );\n console.log('Session created:', response);\n return response;\n } catch (error) {\n console.error('Login error:', error.message);\n throw error;\n }\n}\n\n// 6. Example usage\n(async () => {\n try {\n // Sign up a new user\n const newUser = await signup('user@example.com', 'securePassword123', 'John Doe');\n console.log('User signed up:', newUser);\n\n // Log in with the same credentials\n const session = await login('user@example.com', 'securePassword123');\n console.log('User logged in:', session);\n } catch (error) {\n // Handle errors (e.g., user already exists, invalid credentials)\n }\n})();\n```\n\n### Important notes:\n- Replace `'YOUR_PROJECT_ID'` with your actual Appwrite project ID.\n- The endpoint `https://cloud.appwrite.io/v1` is for Appwrite Cloud. For self‑hosted, use your server URL (e.g., `http://localhost/v1`).\n- Use `'unique()'` as the `userId` to let Appwrite generate a unique ID automatically.\n- After login, the session is stored automatically in the browser (cookie/localStorage) by the SDK. Subsequent requests will be authenticated.\n- For production, never hardcode credentials; use a form or secure input.\n\n### Additional: Check current session\n```javascript\nasync function getCurrentSession() {\n try {\n const user = await account.get();\n console.log('Logged in user:', user);\n return user;\n } catch (error) {\n console.log('No active session:', error.message);\n return null;\n }\n}\n```\n\nThis code covers the core flow: client setup → account creation → session creation.", "correct": true, "score": 0.9, "judgeReasoning": "The answer is nearly complete and correct. It includes: 1) Correct imports from 'appwrite' (Client, Account), 2) Client initialization with setEndpoint() and setProject(), 3) Account service instantiation, 4) account.create() with userId, email, password, and name, 5) account.createEmailPasswordSession() for login. The only minor issue is using 'unique()' as a string literal instead of ID.unique() from the Appwrite SDK (which is the modern recommended approach in v1.x). The reference answer specifically mentions ID.unique(). This is a small but notable difference since ID needs to be imported from 'appwrite'. Everything else is accurate and well-explained.", "promptTokens": 146, "completionTokens": 764, "totalTokens": 910, "cost": 0.000234, "durationMs": 23356, "tokensPerSecond": 32.71, "toolCallCount": 0 }, { "questionId": "auth-5", "category": "auth", "type": "mcq", "question": "What is the purpose of Teams in Appwrite Auth?", "choices": [ "To organize TablesDB tables", "To create separate billing accounts", "To manage deployment environments", "To group users and manage role-based access to resources" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 594, "completionTokens": 194, "totalTokens": 788, "cost": 0.000137, "durationMs": 5086, "tokensPerSecond": 38.14, "toolCallCount": 0 }, { "questionId": "auth-6", "category": "auth", "type": "mcq", "question": "How can you enable Multi-Factor Authentication (MFA) in Appwrite?", "choices": [ "Through the account.createMfaChallenge() and account.updateMFA() methods", "MFA is always enabled by default", "By installing a third-party MFA plugin", "MFA is not supported in Appwrite" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 627, "completionTokens": 169, "totalTokens": 796, "cost": 0.000135, "durationMs": 17877, "tokensPerSecond": 9.45, "toolCallCount": 0 }, { "questionId": "auth-7", "category": "auth", "type": "free-form", "question": "Explain how Appwrite sessions work. How are they created, managed, and deleted? What about session limits?", "correctAnswer": "Sessions represent authenticated user connections. They are created during login, stored as HTTP-only cookies, limited to 10 per user, and can be managed via account.listSessions(), account.deleteSession(), and account.deleteSessions().", "rubric": "Must mention: 1) Sessions created on authentication, 2) Session tokens/cookies, 3) Session limit (10), 4) Methods to list/delete sessions, 5) Session expiry", "modelAnswer": "Appwrite sessions are the core mechanism for managing user authentication state. Each session represents a user logged in on a specific device or browser, and it is tracked by a unique ID and a secret token.\n\n### How Sessions Are Created\nSessions are created when a user authenticates. The main methods are:\n- **Email/Password:** `account.createEmailPasswordSession(email, password)`\n- **OAuth2:** `account.createOAuth2Session(provider, success, failure)`\n- **Magic URL:** `account.createMagicURLSession(userId, email)`\n- **Phone:** `account.createPhoneSession(userId, number)`\n- **Anonymous:** `account.createAnonymousSession()`\n- **JWT:** `account.createJWT()` (creates a short-lived JWT tied to the current session, useful for external API calls)\n- **Server-Side (Admin):** `Users.createSession(userId)` (allows an admin to create a session for a user without their password, e.g., for impersonation)\n\nWhen a session is created, the Appwrite server generates a secret token. The client SDK automatically stores this secret in a secure HTTP‑only cookie (web) or secure local storage (mobile/Flutter). The session object returned includes metadata: IP address, country, OS, browser, device, creation date, expiration date, and MFA factors.\n\n### How Sessions Are Managed\n- **Client-Side:** Users can view all their active devices using `account.listSessions()`. They can get details of a specific session with `account.getSession(sessionId)`.\n- **Server-Side (Admin):** Admins can inspect any user’s sessions via `Users.listSessions(userId)` and `Users.getSession(userId, sessionId)`. They can also update session factors (e.g., marking MFA as verified) with `Users.updateSession(userId, sessionId)`.\n- **MFA Tracking:** The `factors` array in the session object tracks which MFA methods have been verified for that specific session.\n- **Expiration:** Sessions have a configurable lifespan (set in the App Console under **Auth > Settings**). Once expired, the session is automatically invalidated and cleaned up.\n\n### How Sessions Are Deleted\n- **Client-Side (Logout):** A user can delete their current session with `account.deleteSession('current')`, a specific session with `account.deleteSession(sessionId)`, or log out of all devices with `account.deleteSessions()`.\n- **Server-Side (Admin):** Admins can force a logout from a specific device using `Users.deleteSession(userId, sessionId)` or from all devices using `Users.deleteSessions(userId)`.\n- **Automatic Cleanup:** Expired sessions are periodically purged by the Appwrite backend.\n\n### Session Limits\nAppwrite enforces a limit on the number of active sessions per user to prevent table bloat and improve security.\n- **Default Limit:** **100 sessions** per user.\n- **Configuration:** This limit is adjustable in the App Console under **Auth > Settings > Limits**.\n- **Behavior When Limit is Reached:** When a user tries to create a new session and is already at the limit, the **oldest session** is automatically revoked and deleted to make room for the new one. This ensures the user can always log in without manual cleanup, but it also means very old devices are silently logged out.\n\n**Best Practice:** For most applications, the default limit is sufficient. If your users frequently switch devices, consider raising the limit. For high‑security applications, lowering the limit forces users to actively manage their sessions.", "correct": true, "score": 0.7, "judgeReasoning": "The answer is comprehensive and covers most key aspects: sessions created on authentication (multiple methods listed), session tokens/cookies (HTTP-only cookies mentioned), methods to list/delete sessions (account.listSessions(), account.deleteSession(), account.deleteSessions()), and session expiry (configurable lifespan mentioned). However, the session limit is stated as 100 (default, configurable) rather than the reference answer's 10. This is a significant factual discrepancy on a specific rubric point. The answer otherwise goes well beyond the reference in detail and accuracy on other points, covering admin APIs, MFA tracking, and automatic cleanup. Deducting for the incorrect session limit figure.", "promptTokens": 134, "completionTokens": 2449, "totalTokens": 2583, "cost": 0.000704, "durationMs": 107946, "tokensPerSecond": 22.69, "toolCallCount": 0 }, { "questionId": "auth-8", "category": "auth", "type": "mcq", "question": "What does Role.users() represent in Appwrite's permission system?", "choices": [ "Only admin users", "Users in a specific team", "Any user who has an active session (authenticated users)", "Users with verified email addresses only" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 598, "completionTokens": 231, "totalTokens": 829, "cost": 0.000148, "durationMs": 6926, "tokensPerSecond": 33.35, "toolCallCount": 0 }, { "questionId": "auth-9", "category": "auth", "type": "mcq", "question": "How do you authenticate server-side requests in Appwrite?", "choices": [ "Using user session tokens only", "Using OAuth2 tokens", "Server-side requests don't need authentication", "Using an API key with setKey() on the server SDK client" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 606, "completionTokens": 174, "totalTokens": 780, "cost": 0.000134, "durationMs": 4494, "tokensPerSecond": 38.72, "toolCallCount": 0 }, { "questionId": "auth-10", "category": "auth", "type": "mcq", "question": "Which method is used to get the currently logged-in user in Appwrite?", "choices": [ "account.get()", "users.getCurrent()", "auth.currentUser()", "account.getSession()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 577, "completionTokens": 246, "totalTokens": 823, "cost": 0.00015, "durationMs": 5196, "tokensPerSecond": 47.34, "toolCallCount": 0 }, { "questionId": "auth-11", "category": "auth", "type": "mcq", "question": "How do you implement password recovery (forgot password) in Appwrite?", "choices": [ "account.resetPassword(email)", "Only through the Console", "account.createRecovery(email, url) to send the email, then account.updateRecovery(userId, secret, password, passwordAgain) when the user submits the new password", "account.sendPasswordReset(email)" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 651, "completionTokens": 254, "totalTokens": 905, "cost": 0.000162, "durationMs": 8939, "tokensPerSecond": 28.41, "toolCallCount": 0 }, { "questionId": "auth-12", "category": "auth", "type": "mcq", "question": "How long is the password recovery link sent by createRecovery valid?", "choices": [ "1 hour", "15 minutes", "24 hours", "Until used" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 572, "completionTokens": 224, "totalTokens": 796, "cost": 0.000143, "durationMs": 17345, "tokensPerSecond": 12.91, "toolCallCount": 0 }, { "questionId": "auth-13", "category": "auth", "type": "mcq", "question": "What is the default maximum number of sessions per user in an Appwrite project?", "choices": [ "1", "5", "10", "Unlimited" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 565, "completionTokens": 151, "totalTokens": 716, "cost": 0.000121, "durationMs": 4566, "tokensPerSecond": 33.07, "toolCallCount": 0 }, { "questionId": "auth-14", "category": "auth", "type": "mcq", "question": "Which method deletes all sessions for the current user?", "choices": [ "account.logout()", "account.deleteAllSessions()", "account.deleteSession() with no arguments", "account.deleteSessions()" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 588, "completionTokens": 804, "totalTokens": 1392, "cost": 0.000307, "durationMs": 26670, "tokensPerSecond": 30.15, "toolCallCount": 0 }, { "questionId": "auth-15", "category": "auth", "type": "mcq", "question": "What does Role.team(teamId) represent in Appwrite permissions?", "choices": [ "Only users who are members of the specified team", "Any user who is in any team", "Team administrators only", "The team resource itself" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 596, "completionTokens": 284, "totalTokens": 880, "cost": 0.000163, "durationMs": 4916, "tokensPerSecond": 57.77, "toolCallCount": 0 }, { "questionId": "auth-16", "category": "auth", "type": "mcq", "question": "Can you create anonymous (guest) sessions in Appwrite?", "choices": [ "No, anonymous sessions are not supported", "Only with a special API key", "Yes, using account.createAnonymousSession()", "Only in development mode" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 596, "completionTokens": 52, "totalTokens": 648, "cost": 0.000098, "durationMs": 6697, "tokensPerSecond": 7.76, "toolCallCount": 0 }, { "questionId": "auth-17", "category": "auth", "type": "mcq", "question": "When using createRecovery, what requirement applies to the redirect URL?", "choices": [ "It must be HTTPS only", "It can be any URL", "It must match the app's origin exactly", "It must be from a domain you added in the project's platforms in the Console" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 618, "completionTokens": 469, "totalTokens": 1087, "cost": 0.000218, "durationMs": 10600, "tokensPerSecond": 44.25, "toolCallCount": 0 }, { "questionId": "auth-18", "category": "auth", "type": "mcq", "question": "Which MFA factor types does Appwrite support?", "choices": [ "TOTP, phone (SMS), and email", "TOTP only", "TOTP and hardware keys only", "Email only" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 593, "completionTokens": 727, "totalTokens": 1320, "cost": 0.000287, "durationMs": 24517, "tokensPerSecond": 29.65, "toolCallCount": 0 }, { "questionId": "auth-19", "category": "auth", "type": "mcq", "question": "How do you add a user to a team using the client SDK?", "choices": [ "teams.addMember(teamId, userId)", "account.joinTeam(teamId)", "teams.createMembership(teamId, roles, email or userId, etc.)", "users.assignTeam(userId, teamId)" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 625, "completionTokens": 289, "totalTokens": 914, "cost": 0.000168, "durationMs": 13529, "tokensPerSecond": 21.36, "toolCallCount": 0 }, { "questionId": "auth-20", "category": "auth", "type": "free-form", "question": "Explain the difference between account.deleteSession(sessionId) and account.deleteSessions(). When would you use each?", "correctAnswer": "deleteSession(sessionId) removes a single session by ID (e.g. logout on current device). deleteSessions() removes all sessions for the current user (e.g. logout everywhere). Use deleteSession for single-device logout; use deleteSessions for security when user wants to sign out of all devices.", "rubric": "Must mention: 1) deleteSession removes one session by ID, 2) deleteSessions removes all sessions for the user, 3) Use case for each (e.g. logout one device vs logout everywhere)", "modelAnswer": "The core difference between `account.deleteSession(sessionId)` and `account.deleteSessions()` is **scope**:\n\n- **`deleteSession(sessionId)`** targets a **single, specific** session.\n- **`deleteSessions()`** targets **all sessions** belonging to the currently authenticated user.\n\nHere is a detailed breakdown of when to use each:\n\n---\n\n### 1. `account.deleteSession(sessionId)`\n\n**What it does:**\nDeletes exactly one session identified by its unique `sessionId`. If the `sessionId` you pass matches the *current* session, the user is logged out on that device. If it matches a *different* session (e.g., a session on another device), only that remote device is logged out.\n\n**When to use it:**\n- **Device Management UI:** You have a \"Manage Active Sessions\" or \"Security\" page where the user can see a list of their logged-in devices (e.g., \"Chrome on Windows\", \"Safari on iPhone\"). The user can click a \"Revoke\" or \"Logout\" button next to a specific device they no longer recognize or use.\n- **Selective Logout:** The user wants to log out of a public computer they forgot to sign out of, without interrupting their current phone or laptop session.\n\n**Example:**\n```javascript\n// User wants to log out a specific old session\nlet sessionId = \"66a1b2c3d4e5f6g7h8i9j0k1\";\nawait account.deleteSession(sessionId);\n// Only that specific device is logged out.\n```\n\n---\n\n### 2. `account.deleteSessions()`\n\n**What it does:**\nDeletes **every** session for the currently authenticated user. This always includes the current session, meaning the user is immediately logged out on the device where this method is called.\n\n**When to use it:**\n- **\"Log Out of All Devices\" Button:** A standard security feature where the user wants to invalidate every active token.\n- **Security Reset:** Immediately after a user changes their password, enables 2FA, or reports a compromised account. This forces all existing sessions to re-authenticate with the new credentials.\n- **Standard Logout:** If your application's \"Logout\" button is intended to clear all traces of the user across every device, this is the method to use.\n\n**Example:**\n```javascript\n// User clicks \"Sign out everywhere\"\nawait account.deleteSessions();\n// The user is logged out on this device, their phone, their laptop, etc.\n```\n\n---\n\n### Summary Table\n\n| Feature | `deleteSession(sessionId)` | `deleteSessions()` |\n| :--- | :--- | :--- |\n| **Scope** | Single session | All sessions for the user |\n| **Requires ID** | Yes (`sessionId`) | No |\n| **Logs out current device?** | Only if `sessionId` matches the current session | **Always** |\n| **Use Case** | Granular device management (e.g., \"Remove this old phone\") | Global logout / security reset (e.g., \"Log out everywhere\") |", "correct": true, "score": 1, "judgeReasoning": "The model's answer fully covers all three rubric requirements: 1) deleteSession removes one session by its specific ID, 2) deleteSessions removes all sessions for the current user, and 3) clear use cases for each (device management/selective logout vs. logout everywhere/security reset). The answer goes beyond the reference with code examples and a summary table, but all core points are accurately and completely addressed.", "promptTokens": 135, "completionTokens": 2084, "totalTokens": 2219, "cost": 0.000602, "durationMs": 64906, "tokensPerSecond": 32.11, "toolCallCount": 0 }, { "questionId": "db-1", "category": "tablesdb", "type": "mcq", "question": "What is the hierarchy of data organization in the current Appwrite TablesDB API?", "choices": [ "Database > Collection > Document", "TablesDB > Table > Row", "Schema > Collection > Record", "Project > Database > Table" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 593, "completionTokens": 2349, "totalTokens": 2942, "cost": 0.000741, "durationMs": 110999, "tokensPerSecond": 21.16, "toolCallCount": 0 }, { "questionId": "db-2", "category": "tablesdb", "type": "mcq", "question": "Which column types are supported in Appwrite TablesDB tables?", "choices": [ "String, Integer, Float only", "String, Number, Boolean only", "Any JSON type without schema validation", "Varchar/Text, Integer, Float, Boolean, DateTime, Email, URL, IP, Enum, Relationship" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 627, "completionTokens": 193, "totalTokens": 820, "cost": 0.000142, "durationMs": 4886, "tokensPerSecond": 39.5, "toolCallCount": 0 }, { "questionId": "db-3", "category": "tablesdb", "type": "free-form", "question": "Write code using the current Appwrite Web SDK TablesDB API to create a database, a table with columns, and insert a row. Use a \"tasks\" table with title (varchar), completed (boolean), and dueDate (datetime) columns.", "correctAnswer": "Use the TablesDB service to create a database, create a tasks table with columns (varchar title, boolean completed, datetime dueDate), then createRow with the data object.", "rubric": "Must include: 1) Client + TablesDB setup, 2) tablesDB.create() for database, 3) tablesDB.createTable() for the tasks table, 4) Creating varchar, boolean, and datetime columns, 5) tablesDB.createRow() with data", "modelAnswer": "Below is an example using the **Appwrite Web SDK (v1.x)** with the **Databases service** (the current API for managing tables/collections and documents). The code creates a database, a `tasks` collection with the specified columns, and inserts one row.\n\n```javascript\nimport { Client, Databases } from 'appwrite';\n\n// 1. Initialize the client\nconst client = new Client()\n .setEndpoint('https://cloud.appwrite.io/v1') // Your Appwrite endpoint\n .setProject(''); // Your project ID\n\nconst databases = new Databases(client);\n\nasync function setupTasksDatabase() {\n try {\n // 2. Create a database (if it doesn't exist)\n const database = await databases.create(\n 'unique()', // Database ID (use 'unique()' for auto‑generated)\n 'MyTasksDB' // Database name\n );\n const databaseId = database.$id;\n console.log(`Database created: ${databaseId}`);\n\n // 3. Create a collection (table) named \"tasks\"\n const collection = await databases.createCollection(\n databaseId,\n 'unique()', // Collection ID\n 'tasks', // Collection name\n [ // Permissions (read/write for any role)\n 'read(\"any\")',\n 'write(\"any\")'\n ]\n );\n const collectionId = collection.$id;\n console.log(`Collection created: ${collectionId}`);\n\n // 4. Create attributes (columns)\n // Note: Attributes are created asynchronously; we wait for each to be \"available\"\n const titleAttr = await databases.createStringAttribute(\n databaseId,\n collectionId,\n 'title', // Attribute key\n 255, // Max length\n true // Required\n );\n await waitForAttribute(databaseId, collectionId, 'title');\n console.log('Attribute \"title\" created');\n\n const completedAttr = await databases.createBooleanAttribute(\n databaseId,\n collectionId,\n 'completed',\n true // Required\n );\n await waitForAttribute(databaseId, collectionId, 'completed');\n console.log('Attribute \"completed\" created');\n\n const dueDateAttr = await databases.createDatetimeAttribute(\n databaseId,\n collectionId,\n 'dueDate',\n false // Not required\n );\n await waitForAttribute(databaseId, collectionId, 'dueDate');\n console.log('Attribute \"dueDate\" created');\n\n // 5. Insert a document (row)\n const document = await databases.createDocument(\n databaseId,\n collectionId,\n 'unique()', // Document ID\n {\n title: 'Buy groceries',\n completed: false,\n dueDate: '2025-03-15T10:00:00.000+00:00' // ISO 8601 format\n }\n );\n console.log('Document inserted:', document.$id);\n\n } catch (error) {\n console.error('Error:', error);\n }\n}\n\n// Helper: wait until an attribute is marked as \"available\"\nasync function waitForAttribute(databaseId, collectionId, attributeKey) {\n let attribute;\n do {\n await new Promise(resolve => setTimeout(resolve, 500)); // poll every 500ms\n const collection = await databases.getCollection(databaseId, collectionId);\n attribute = collection.attributes.find(attr => attr.key === attributeKey);\n } while (attribute && attribute.status !== 'available');\n}\n\n// Run the setup\nsetupTasksDatabase();\n```\n\n### Important notes\n\n- **SDK version**: This code uses the **Appwrite Web SDK v1.x** (the current stable release). The `Databases` service replaces the older “Tables” API.\n- **Permissions**: The example grants read/write to `any` role. Adjust according to your security requirements.\n- **Attribute availability**: After creating an attribute, it may take a moment to become `available`. The helper function `waitForAttribute` polls until the attribute is ready before inserting data.\n- **IDs**: Using `'unique()'` generates a unique ID automatically. You can also supply your own string.\n- **Date format**: The `dueDate` attribute expects an ISO 8601 string (e.g., `'2025-03-15T10:00:00.000+00:00'`).\n\nReplace `` with your actual Appwrite project ID and adjust the endpoint if you are using a self‑hosted instance.", "correct": false, "score": 0.1, "judgeReasoning": "The question specifically asks about the 'TablesDB API' which appears to be a fictional/non-existent Appwrite API. The reference answer confirms this by mentioning TablesDB service with methods like tablesDB.create(), tablesDB.createTable(), and tablesDB.createRow(). The model's answer instead uses the standard Appwrite Databases service (which is the real current API), with collections, attributes, and documents. While the model's code is technically correct for the actual Appwrite SDK, it completely ignores the TablesDB API requirement specified in the question and reference answer. The model should have either used the TablesDB API as specified or noted that it doesn't exist. The model even explicitly states 'The Databases service replaces the older Tables API' which contradicts the premise of the question. Since the answer doesn't use TablesDB, tablesDB.create(), tablesDB.createTable(), or tablesDB.createRow() as required by the rubric, it scores very low.", "promptTokens": 163, "completionTokens": 1629, "totalTokens": 1792, "cost": 0.000479, "durationMs": 22696, "tokensPerSecond": 71.77, "toolCallCount": 0 }, { "questionId": "db-4", "category": "tablesdb", "type": "mcq", "question": "In TablesDB, you need rows whose status is exactly either \"open\" or \"blocked\". Which query is the correct Appwrite Query syntax?", "choices": [ "Query.equal('status', ['open', 'blocked'])", "Query.equal(['open', 'blocked'], 'status')", "Query.where('status').in(['open', 'blocked'])", "Query.filter('status', 'in', ['open', 'blocked'])" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 666, "completionTokens": 150, "totalTokens": 816, "cost": 0.000135, "durationMs": 5740, "tokensPerSecond": 26.13, "toolCallCount": 0 }, { "questionId": "db-5", "category": "tablesdb", "type": "mcq", "question": "Why would you add an index to a TablesDB column that is frequently filtered or sorted?", "choices": [ "To make the column immutable after the first row is inserted", "To let queries on that column run efficiently at scale", "To automatically create relationship columns between tables", "To store the column outside the row size limit" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 627, "completionTokens": 163, "totalTokens": 790, "cost": 0.000133, "durationMs": 5225, "tokensPerSecond": 31.2, "toolCallCount": 0 }, { "questionId": "db-6", "category": "tablesdb", "type": "free-form", "question": "Explain how to query rows in Appwrite TablesDB using the Query class. Show examples of filtering, sorting, limiting, and pagination.", "correctAnswer": "The Query class provides methods like equal(), greaterThan(), lessThan(), orderAsc(), orderDesc(), limit(), offset(), cursorAfter() that are passed as an array to tablesDB.listRows().", "rubric": "Must include: 1) Query.equal() for filtering, 2) Query.orderDesc() or orderAsc() for sorting, 3) Query.limit() and Query.offset() for pagination, 4) Passing queries array to listRows(), 5) At least one other query method", "modelAnswer": "Appwrite's database service stores data as **Documents** inside **Collections** (not rows in tables, but the concept is analogous). The `Query` class provides static methods to build filters, sorting, and pagination parameters for the `listDocuments()` method.\n\n### 1. Setup\n```javascript\nimport { Client, Databases, Query } from 'appwrite';\n\nconst client = new Client()\n .setEndpoint('https://cloud.appwrite.io/v1')\n .setProject('');\n\nconst databases = new Databases(client);\n```\n\n### 2. Filtering\nAll filters are combined with **AND** logic.\n\n```javascript\n// Equality\nQuery.equal('status', 'active')\nQuery.equal('category', ['tech', 'gaming']) // Array match (OR within the array)\n\n// Inequality\nQuery.notEqual('role', 'banned')\n\n// Comparison\nQuery.lessThan('price', 50)\nQuery.greaterThan('age', 18)\nQuery.lessThanEqual('rating', 4.5)\nQuery.greaterThanEqual('stock', 1)\n\n// Text Search (requires a fulltext index)\nQuery.search('title', 'laptop')\n\n// Array Contains\nQuery.contains('tags', 'sale')\n```\n\n### 3. Sorting\n```javascript\nQuery.orderAsc('name')\nQuery.orderDesc('createdAt')\n```\n\n### 4. Limiting\n```javascript\nQuery.limit(25) // Max 100 per request\n```\n\n### 5. Pagination\n\n**Offset Pagination** (simple, but less performant on large datasets):\n```javascript\n// Page 1\n[Query.limit(10), Query.offset(0)]\n// Page 2\n[Query.limit(10), Query.offset(10)]\n```\n\n**Cursor Pagination** (recommended for real-time data):\n```javascript\n// First page\nlet response = await databases.listDocuments(\n 'DATABASE_ID',\n 'COLLECTION_ID',\n [Query.limit(10), Query.orderAsc('$id')]\n);\n\n// Next page\nlet nextPage = await databases.listDocuments(\n 'DATABASE_ID',\n 'COLLECTION_ID',\n [\n Query.limit(10),\n Query.orderAsc('$id'),\n Query.cursorAfter(response.documents[response.documents.length - 1].$id)\n ]\n);\n\n// Previous page\nlet prevPage = await databases.listDocuments(\n 'DATABASE_ID',\n 'COLLECTION_ID',\n [\n Query.limit(10),\n Query.orderAsc('$id'),\n Query.cursorBefore(response.documents[0].$id)\n ]\n);\n```\n\n### 6. Complete Example\n```javascript\nasync function getPublishedProducts(page = 0) {\n const queries = [\n Query.equal('status', 'published'),\n Query.greaterThan('stock', 0),\n Query.orderDesc('createdAt'),\n Query.limit(20),\n Query.offset(page * 20)\n ];\n\n const response = await databases.listDocuments(\n 'DATABASE_ID',\n 'COLLECTION_ID',\n queries\n );\n\n return response;\n}\n```\n\n### ⚠️ Important Notes\n- **Indexes are required.** You must create an index in the Appwrite Console for every attribute you filter or sort by (e.g., an index on `status` for `equal`, or a fulltext index on `title` for `search`).\n- **AND logic only.** You cannot combine queries with OR in a single `listDocuments` call.\n- **Cursor pagination** is more reliable than offset pagination when documents are frequently added or removed.", "correct": false, "score": 0.3, "judgeReasoning": "The model's answer describes Appwrite's standard Databases service (listDocuments, Collections, Documents) rather than the TablesDB service (listRows, TablesDB). The question specifically asks about 'TablesDB' and 'rows', which appears to be a different/newer Appwrite feature. However, evaluating against the rubric criteria: 1) Query.equal() is shown ✓, 2) Query.orderDesc()/orderAsc() is shown ✓, 3) Query.limit() and Query.offset() are shown ✓, 4) Passing queries array - but to listDocuments() not listRows() ✗, 5) Multiple other query methods shown (greaterThan, lessThan, cursorAfter, etc.) ✓. The answer fails on the critical point of using listRows() instead of listDocuments(), and uses the wrong service entirely (Databases vs TablesDB). Since the question is specifically about TablesDB and the answer describes a completely different service, this is a significant miss, though the Query class concepts are largely transferable.", "promptTokens": 140, "completionTokens": 2527, "totalTokens": 2667, "cost": 0.000727, "durationMs": 27017, "tokensPerSecond": 93.53, "toolCallCount": 0 }, { "questionId": "db-7", "category": "tablesdb", "type": "mcq", "question": "What types of relationships does Appwrite support between tables?", "choices": [ "One-to-one, one-to-many, many-to-one, and many-to-many", "Only one-to-one", "Only foreign key references", "Relationships are not supported" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 606, "completionTokens": 108, "totalTokens": 714, "cost": 0.000115, "durationMs": 11924, "tokensPerSecond": 9.06, "toolCallCount": 0 }, { "questionId": "db-8", "category": "tablesdb", "type": "mcq", "question": "How do permissions work on rows in Appwrite?", "choices": [ "Rows inherit permissions from the project only", "Permissions are set globally for all rows", "Each row can have its own permission list, or inherit from the table", "Permissions are only managed through API keys" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 621, "completionTokens": 155, "totalTokens": 776, "cost": 0.00013, "durationMs": 7256, "tokensPerSecond": 21.36, "toolCallCount": 0 }, { "questionId": "db-9", "category": "tablesdb", "type": "mcq", "question": "What is the correct method to update a row with the current TablesDB API?", "choices": [ "tablesDB.update()", "tablesDB.patchRow()", "tablesDB.updateRow({ databaseId, tableId, rowId, data })", "rows.update()" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 606, "completionTokens": 569, "totalTokens": 1175, "cost": 0.000244, "durationMs": 34583, "tokensPerSecond": 16.45, "toolCallCount": 0 }, { "questionId": "db-10", "category": "tablesdb", "type": "mcq", "question": "Which Query method performs a full-text search on a row column?", "choices": [ "Query.search()", "Query.contains()", "Query.fullText()", "Query.like()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 573, "completionTokens": 857, "totalTokens": 1430, "cost": 0.00032, "durationMs": 37594, "tokensPerSecond": 22.8, "toolCallCount": 0 }, { "questionId": "db-11", "category": "tablesdb", "type": "mcq", "question": "How do transactions work in Appwrite TablesDB?", "choices": [ "Transactions are not supported", "Wrap operations in a single tablesDB.transaction() call", "Create a transaction, pass the transactionId to row create/update/delete operations, then commit the transaction", "Use a special transaction table" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 627, "completionTokens": 347, "totalTokens": 974, "cost": 0.000185, "durationMs": 10646, "tokensPerSecond": 32.59, "toolCallCount": 0 }, { "questionId": "db-12", "category": "tablesdb", "type": "mcq", "question": "What are the possible statuses of a TablesDB transaction?", "choices": [ "pending, committing, committed, failed", "pending, committing, committed, rolled_back, failed", "open, closed", "started, finished" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 593, "completionTokens": 528, "totalTokens": 1121, "cost": 0.000231, "durationMs": 43454, "tokensPerSecond": 12.15, "toolCallCount": 0 }, { "questionId": "db-13", "category": "tablesdb", "type": "mcq", "question": "Which Query method is used for cursor-based pagination (get next page after a row)?", "choices": [ "Query.cursorAfter(rowId) or Query.cursorBefore(rowId)", "Query.offset()", "Query.nextPage()", "Query.cursor()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 603, "completionTokens": 234, "totalTokens": 837, "cost": 0.00015, "durationMs": 17029, "tokensPerSecond": 13.74, "toolCallCount": 0 }, { "questionId": "db-14", "category": "tablesdb", "type": "mcq", "question": "How do you delete a row with the current TablesDB API?", "choices": [ "tablesDB.delete()", "rows.delete()", "tablesDB.removeRow()", "tablesDB.deleteRow({ databaseId, tableId, rowId })" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 597, "completionTokens": 455, "totalTokens": 1052, "cost": 0.000211, "durationMs": 48600, "tokensPerSecond": 9.36, "toolCallCount": 0 }, { "questionId": "db-15", "category": "tablesdb", "type": "mcq", "question": "When creating a row, can you set permissions on that row?", "choices": [ "Yes, pass a permissions array to createRow", "No, rows always inherit table permissions", "Only via the Console", "Only for the row creator" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 598, "completionTokens": 306, "totalTokens": 904, "cost": 0.000169, "durationMs": 6671, "tokensPerSecond": 45.87, "toolCallCount": 0 }, { "questionId": "db-16", "category": "tablesdb", "type": "mcq", "question": "What is a relationship column in Appwrite?", "choices": [ "A link to an external API", "A special index type", "A column that references rows in the same or another table (one-to-one, one-to-many, etc.)", "A computed field" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 615, "completionTokens": 200, "totalTokens": 815, "cost": 0.000142, "durationMs": 7509, "tokensPerSecond": 26.63, "toolCallCount": 0 }, { "questionId": "db-17", "category": "tablesdb", "type": "mcq", "question": "You want the first page of a TablesDB query to return no more than 20 rows. Which query should be included in the queries array?", "choices": [ "Query.page(20)", "Query.max(20)", "Query.limit(20)", "Query.count(20)" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 599, "completionTokens": 134, "totalTokens": 733, "cost": 0.000121, "durationMs": 9290, "tokensPerSecond": 14.42, "toolCallCount": 0 }, { "questionId": "db-18", "category": "tablesdb", "type": "mcq", "question": "Which query sorts TablesDB rows by a `score` column from highest to lowest?", "choices": [ "Query.orderDesc('score')", "Query.sort('score', 'desc')", "Query.descending('score')", "Query.orderBy('score', Query.DESC)" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 610, "completionTokens": 252, "totalTokens": 862, "cost": 0.000156, "durationMs": 65882, "tokensPerSecond": 3.83, "toolCallCount": 0 }, { "questionId": "db-19", "category": "tablesdb", "type": "mcq", "question": "What happens if a transaction expires before it is committed?", "choices": [ "Operations are automatically rolled back and the transaction is deleted", "The transaction is committed automatically", "Staged operations fail with a transaction expired error; the transaction has a TTL", "Nothing; transactions do not expire" ], "correctAnswer": "C", "modelAnswer": "A", "correct": false, "score": 0, "promptTokens": 620, "completionTokens": 517, "totalTokens": 1137, "cost": 0.000232, "durationMs": 24339, "tokensPerSecond": 21.24, "toolCallCount": 0 }, { "questionId": "db-20", "category": "tablesdb", "type": "free-form", "question": "Explain how to use Query to filter rows where a numeric field is greater than 100 and return at most 20 results sorted by that field descending.", "correctAnswer": "Use tablesDB.listRows() with queries array: Query.greaterThan('columnId', 100), Query.orderDesc('columnId'), Query.limit(20). Pass these to the listRows queries parameter.", "rubric": "Must include: 1) Query.greaterThan for the filter, 2) Query.orderDesc for sort, 3) Query.limit(20), 4) Passing queries to listRows()", "modelAnswer": "To filter documents where a numeric field is greater than 100, limit to 20 results, and sort descending by that field, use the Appwrite **Query** class with `greaterThan`, `limit`, and `orderDesc` methods. Combine them in the `listDocuments` call.\n\n**Example (JavaScript SDK):**\n\n```javascript\nimport { Query } from 'appwrite';\n\nconst response = await databases.listDocuments(\n '',\n '',\n [\n Query.greaterThan('fieldName', 100),\n Query.orderDesc('fieldName'),\n Query.limit(20)\n ]\n);\n```\n\n**Explanation:**\n\n- `Query.greaterThan('fieldName', 100)` – filters rows where `fieldName` > 100.\n- `Query.orderDesc('fieldName')` – sorts results by `fieldName` in descending order.\n- `Query.limit(20)` – returns at most 20 documents.\n\n**Important notes:**\n\n- The field used in `greaterThan` and `orderDesc` must have an **index** in the Appwrite collection (create it in the collection’s “Indexes” tab).\n- The order of queries matters: `greaterThan` and `orderDesc` should be placed before `limit` for optimal performance.\n- If you need ascending order, use `Query.orderAsc('fieldName')`.\n\nFor other SDKs (Python, Dart, etc.), the syntax is similar—just import `Query` and use the same static methods.", "correct": true, "score": 0.9, "judgeReasoning": "The answer includes all four required elements: Query.greaterThan for filtering, Query.orderDesc for sorting, Query.limit(20), and passing queries to a list method. The only minor discrepancy is that the answer uses listDocuments() (for Appwrite Databases/Collections) rather than listRows() (for Appwrite Tables/tablesDB as specified in the reference answer). The core Query logic is completely correct, and the answer is well-explained with proper code examples. The difference between listDocuments and listRows reflects different Appwrite APIs, but the Query usage pattern is identical and correct.", "promptTokens": 142, "completionTokens": 470, "totalTokens": 612, "cost": 0.000151, "durationMs": 9601, "tokensPerSecond": 48.95, "toolCallCount": 0 }, { "questionId": "db-21", "category": "tablesdb", "type": "mcq", "question": "What are the minimum and maximum values for an integer column in Appwrite?", "choices": [ "-2147483648 to 2147483647 (32-bit signed integer)", "-9223372036854775808 to 9223372036854775807 (64-bit signed integer)", "0 to 18446744073709551615 (64-bit unsigned integer)", "-999999999999 to 999999999999 (12-digit limit)" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 689, "completionTokens": 671, "totalTokens": 1360, "cost": 0.000284, "durationMs": 25086, "tokensPerSecond": 26.75, "toolCallCount": 0 }, { "questionId": "db-22", "category": "tablesdb", "type": "mcq", "question": "Which of the following is NOT a valid string-based column type in Appwrite TablesDB?", "choices": [ "varchar", "mediumtext", "tinytext", "longtext" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 567, "completionTokens": 1202, "totalTokens": 1769, "cost": 0.000416, "durationMs": 33650, "tokensPerSecond": 35.72, "toolCallCount": 0 }, { "questionId": "db-23", "category": "tablesdb", "type": "mcq", "question": "Which of the following is NOT a valid string-related column type in Appwrite TablesDB?", "choices": [ "email", "url", "enum", "uuid" ], "correctAnswer": "D", "modelAnswer": "D", "correct": true, "score": 1, "promptTokens": 561, "completionTokens": 14125, "totalTokens": 14686, "cost": 0.004034, "durationMs": 356268, "tokensPerSecond": 39.65, "toolCallCount": 0 }, { "questionId": "func-1", "category": "functions", "type": "mcq", "question": "Which runtimes does Appwrite Functions support?", "choices": [ "Node.js only", "Node.js, Python, PHP, Ruby, Dart, Deno, Swift, Kotlin, Java, Bun, and more", "Node.js and Python only", "Any Docker container" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 616, "completionTokens": 167, "totalTokens": 783, "cost": 0.000133, "durationMs": 4409, "tokensPerSecond": 37.88, "toolCallCount": 0 }, { "questionId": "func-2", "category": "functions", "type": "mcq", "question": "How are environment variables provided to Appwrite Functions?", "choices": [ "Through a .env file in the function directory", "Set in the Appwrite Console or API, accessible at runtime", "Hardcoded in the function code", "Through command-line arguments" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 609, "completionTokens": 167, "totalTokens": 776, "cost": 0.000132, "durationMs": 5198, "tokensPerSecond": 32.13, "toolCallCount": 0 }, { "questionId": "func-3", "category": "functions", "type": "free-form", "question": "Write an Appwrite Function in Node.js that receives a JSON body with a \"name\" field and returns a personalized greeting. Use the correct function signature and response format.", "correctAnswer": "Appwrite Functions use export default async ({ req, res, log, error }) => {} signature. Request body is in req.body. Response uses res.json(), res.text(), res.empty(), or res.redirect().", "rubric": "Must include: 1) Default export of async function, 2) Destructured context with req, res, log or error, 3) Parsing req.body, 4) Using res.json() for response, 5) Correct function signature pattern", "modelAnswer": "Here's the correct Appwrite Function in Node.js:\n\n```javascript\nmodule.exports = async function (req, res) {\n // req.body is automatically parsed if Content-Type is application/json\n const { name } = req.body;\n\n // Return a JSON response with the greeting\n res.json({ greeting: `Hello, ${name}!` });\n};\n```\n\n**Key points:**\n- The function signature uses `async (req, res)` as required by Appwrite.\n- `req.body` contains the parsed JSON payload (Appwrite handles parsing automatically).\n- `res.json()` sends a JSON response with the correct `Content-Type` header.\n- The response format is `{ \"greeting\": \"Hello, !\" }`.\n\nFor production, you may want to add validation:\n\n```javascript\nmodule.exports = async function (req, res) {\n const { name } = req.body || {};\n\n if (!name || typeof name !== 'string') {\n return res.json({ error: 'Missing or invalid \"name\" field' }, 400);\n }\n\n res.json({ greeting: `Hello, ${name}!` });\n};\n```", "correct": false, "score": 0.3, "judgeReasoning": "The answer uses the wrong function signature for Appwrite Functions. Appwrite Functions require 'export default async ({ req, res, log, error }) => {}' (default export with destructured context object), not 'module.exports = async function(req, res)'. The answer uses CommonJS module.exports with separate req/res parameters, which is the Express.js pattern, not Appwrite's pattern. It does correctly use req.body for parsing and res.json() for the response, which accounts for partial credit. The destructured context with log/error is missing, and the default export pattern is wrong.", "promptTokens": 146, "completionTokens": 914, "totalTokens": 1060, "cost": 0.000276, "durationMs": 77967, "tokensPerSecond": 11.72, "toolCallCount": 0 }, { "questionId": "func-4", "category": "functions", "type": "mcq", "question": "What are the ways to trigger an Appwrite Function execution?", "choices": [ "HTTP requests only", "HTTP requests, event triggers, scheduled (CRON), and manual execution via API/Console", "Only through the Appwrite Console", "Only through webhooks" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 609, "completionTokens": 212, "totalTokens": 821, "cost": 0.000145, "durationMs": 4869, "tokensPerSecond": 43.54, "toolCallCount": 0 }, { "questionId": "func-5", "category": "functions", "type": "mcq", "question": "What is the purpose of the \"build command\" in an Appwrite Function configuration?", "choices": [ "To compile the function to machine code", "To run commands during deployment to install dependencies and prepare the function", "To build the Appwrite server", "To create a Docker image" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 612, "completionTokens": 242, "totalTokens": 854, "cost": 0.000153, "durationMs": 6970, "tokensPerSecond": 34.72, "toolCallCount": 0 }, { "questionId": "func-6", "category": "functions", "type": "mcq", "question": "How can an Appwrite Function access other Appwrite services like TablesDB?", "choices": [ "Functions cannot access other Appwrite services", "By importing the Node.js SDK and using the function's API key or the APPWRITE_FUNCTION_API_ENDPOINT and APPWRITE_FUNCTION_PROJECT_ID environment variables", "Through REST API calls only with no SDK support", "By directly accessing the database filesystem" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 668, "completionTokens": 283, "totalTokens": 951, "cost": 0.000173, "durationMs": 8703, "tokensPerSecond": 32.52, "toolCallCount": 0 }, { "questionId": "func-7", "category": "functions", "type": "free-form", "question": "Explain how to deploy an Appwrite Function using the Appwrite CLI. What are the steps and key configuration options?", "correctAnswer": "Appwrite CLI enables function deployment through init (appwrite init functions) and push (appwrite push functions) commands. Configuration is stored in appwrite.config.json including runtime, entrypoint, build commands, execute permissions, variables, and schedule.", "rubric": "Must mention: 1) CLI installation, 2) appwrite init functions, 3) Configuration in appwrite.config.json, 4) appwrite push functions, 5) Key options like runtime, entrypoint, build commands, permissions, variables, or schedule", "modelAnswer": "Deploying an Appwrite Function via the CLI follows a **init → develop → deploy** workflow. Here are the exact steps and the key configuration options you need to know.\n\n### Prerequisites\n```bash\nnpm install -g appwrite-cli\nappwrite login\nappwrite init project\n```\n\n---\n\n### Step 1: Initialize the Function\n```bash\nappwrite init function\n```\nThis creates a local directory for your function and an `appwrite.json` configuration file. You will be prompted for:\n\n- **Name**: Human-readable function name.\n- **Runtime**: Node.js, Python, Dart, PHP, Ruby, .NET, Kotlin, Swift, Deno.\n- **Entrypoint**: The main file (e.g., `src/index.js`).\n- **Build Commands**: Commands to install dependencies (e.g., `npm install`, `pip install -r requirements.txt`).\n\n---\n\n### Step 2: Develop the Function\nWrite your code in the entrypoint file. The function receives a standard context object.\n\n**Node.js Example:**\n```javascript\nexport default async ({ req, res, log, error }) => {\n log('Function executed');\n return res.json({ message: 'Hello from Appwrite!' });\n}\n```\n\n---\n\n### Step 3: Deploy the Function\n```bash\nappwrite deploy function\n```\nOr target a specific function:\n```bash\nappwrite deploy function --functionId \n```\n\n**Key Configuration Options during deployment:**\n\n| Flag | Purpose |\n|---|---|\n| `--activate` | Activate the function immediately after deployment (default: `true`). |\n| `--entrypoint` | Override the entrypoint defined in `appwrite.json`. |\n| `--commands` | Override the build commands for this deployment. |\n| `--ignore` | Exclude files/directories (e.g., `--ignore \"node_modules .git\"`). Respects `.gitignore` by default. |\n| `--vars` | Set environment variables inline (e.g., `--vars \"KEY=VALUE,KEY2=VALUE2\"`). |\n\n**What happens during deployment?**\nThe CLI creates a tarball of your function directory (respecting ignore rules), uploads it to Appwrite, and the server executes the build commands. The function is then ready to run.\n\n---\n\n### Step 4: Configure Triggers & Settings (Console / API)\nThe CLI handles code deployment, but triggers and execution settings are typically managed via the Appwrite Console or Management API:\n\n- **Triggers**:\n - **HTTP**: Exposes the function as a REST endpoint.\n - **Schedule**: Runs on a CRON expression.\n - **Event**: Reacts to Appwrite system events (e.g., `users.*.create`, `databases.*.documents.*.update`).\n- **Permissions**: Set who can execute the function (`any`, `users`, `guests`, `teams`).\n- **Settings**: Timeout (max 900s), Memory (128MB – 512MB).\n\n---\n\n### Step 5: Manage Environment Variables\n```bash\n# Create a variable\nappwrite create variable --functionId --key --value \n\n# Update a variable\nappwrite update variable --functionId --variableId --key --value \n```\n\n---\n\n### Deep Dive: `appwrite.json`\nThe `appwrite.json` file is the source of truth for your function configuration. You can edit it directly to manage multiple functions.\n\n```json\n{\n \"projectId\": \"YOUR_PROJECT_ID\",\n \"functions\": [\n {\n \"$id\": \"FUNCTION_ID\",\n \"name\": \"My Function\",\n \"runtime\": \"node-18.0\",\n \"path\": \"functions/my-function\",\n \"entrypoint\": \"src/index.js\",\n \"ignore\": [\"node_modules/.bin\"],\n \"commands\": \"npm install\",\n \"vars\": {\n \"APPWRITE_FUNCTION_ENDPOINT\": \"https://cloud.appwrite.io/v1\"\n }\n }\n ]\n}\n```\n\n**Key fields in `appwrite.json`:**\n- `path`: Relative path to the function directory.\n- `ignore`: Files to exclude from the deployment archive.\n- `commands`: Build commands executed on the server.\n- `vars`: Environment variables deployed with the function.\n\n---\n\n### Best Practices\n- **Keep functions stateless** – rely on environment variables and Appwrite services for state.\n- **Use `.gitignore`** to prevent large files (e.g., `node_modules`) from being uploaded.\n- **Test locally** with `appwrite run function` before deploying.\n- **Use `--ignore`** to exclude unnecessary files and speed up deployments.", "correct": true, "score": 0.85, "judgeReasoning": "The answer covers most of the required rubric points well: CLI installation (npm install -g appwrite-cli), appwrite init function (Step 1), configuration in appwrite.json (Step 5 deep dive), deployment command (Step 3 - uses 'appwrite deploy function' instead of 'appwrite push functions'), and key options like runtime, entrypoint, build commands, permissions, variables, and schedule. Minor deductions: the deployment command used is 'appwrite deploy function' rather than 'appwrite push functions' as specified in the reference answer, and the config file is named 'appwrite.json' rather than 'appwrite.config.json'. These are minor discrepancies that may reflect different CLI versions, but the core concepts and workflow are accurately and thoroughly covered.", "promptTokens": 135, "completionTokens": 3186, "totalTokens": 3321, "cost": 0.000911, "durationMs": 33969, "tokensPerSecond": 93.79, "toolCallCount": 0 }, { "questionId": "func-8", "category": "functions", "type": "mcq", "question": "What context parameters does an Appwrite Function receive?", "choices": [ "request and response only", "req, res, log, and error", "event, context, and callback", "input, output, and logger" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 593, "completionTokens": 422, "totalTokens": 1015, "cost": 0.000201, "durationMs": 55673, "tokensPerSecond": 7.58, "toolCallCount": 0 }, { "questionId": "func-9", "category": "functions", "type": "mcq", "question": "How do you schedule an Appwrite Function to run periodically?", "choices": [ "Using JavaScript setTimeout()", "Using a CRON expression in the function configuration", "Through an external scheduler service", "Scheduled execution is not supported" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 592, "completionTokens": 109, "totalTokens": 701, "cost": 0.000113, "durationMs": 6389, "tokensPerSecond": 17.06, "toolCallCount": 0 }, { "questionId": "func-10", "category": "functions", "type": "mcq", "question": "What response methods are available in Appwrite Functions?", "choices": [ "res.send() only", "res.json(), res.text(), res.empty(), res.redirect()", "res.write() and res.end()", "return JSON.stringify(data)" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 600, "completionTokens": 327, "totalTokens": 927, "cost": 0.000176, "durationMs": 8972, "tokensPerSecond": 36.45, "toolCallCount": 0 }, { "questionId": "func-11", "category": "functions", "type": "mcq", "question": "What are the possible statuses of an Appwrite Function execution?", "choices": [ "pending, running, done, error", "waiting, processing, completed, failed, and scheduled", "queued, active, success, failure", "created, started, finished, crashed" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 612, "completionTokens": 305, "totalTokens": 917, "cost": 0.000171, "durationMs": 8145, "tokensPerSecond": 37.45, "toolCallCount": 0 }, { "questionId": "func-12", "category": "functions", "type": "mcq", "question": "When you call the SDK's createExecution with async: true, what happens?", "choices": [ "The request fails because async is not supported", "The API returns immediately with execution status 'waiting'; the function runs in the background and you can poll Get Execution for updates", "The client must provide a webhook URL to receive the result", "The execution is queued but never runs" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 657, "completionTokens": 311, "totalTokens": 968, "cost": 0.000179, "durationMs": 6982, "tokensPerSecond": 44.54, "toolCallCount": 0 }, { "questionId": "func-13", "category": "functions", "type": "mcq", "question": "Can an Appwrite Function be triggered by an event from another function's execution (e.g. functions.*.executions.*.create)?", "choices": [ "Yes, function execution events are supported like any other event", "No; triggering a function on a function event (events starting with 'functions.') is not allowed", "Only in the Console, not via event configuration", "Yes, but only for completed executions" ], "correctAnswer": "B", "modelAnswer": "A", "correct": false, "score": 0, "promptTokens": 657, "completionTokens": 382, "totalTokens": 1039, "cost": 0.000199, "durationMs": 12347, "tokensPerSecond": 30.94, "toolCallCount": 0 }, { "questionId": "func-14", "category": "functions", "type": "mcq", "question": "When can you successfully execute an Appwrite Function via the API?", "choices": [ "As soon as the function resource is created", "Only after the function has an active deployment whose build status is 'ready'", "After the first deployment is created, regardless of build status", "Only when the deployment status is 'building'" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 633, "completionTokens": 162, "totalTokens": 795, "cost": 0.000134, "durationMs": 7467, "tokensPerSecond": 21.7, "toolCallCount": 0 }, { "questionId": "func-15", "category": "functions", "type": "mcq", "question": "Besides functionId and data, what parameters does the createExecution API support?", "choices": [ "None", "async only", "async, path, method, headers, and scheduledAt (ISO 8601)", "path and method only" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 596, "completionTokens": 309, "totalTokens": 905, "cost": 0.00017, "durationMs": 11563, "tokensPerSecond": 26.72, "toolCallCount": 0 }, { "questionId": "func-16", "category": "functions", "type": "mcq", "question": "When passing custom headers to createExecution, what restriction applies?", "choices": [ "Headers are not allowed; only the request body is passed", "Header names cannot start with 'x-appwrite-'; they are reserved by Appwrite", "Only Content-Type is allowed", "There are no restrictions on header names" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 629, "completionTokens": 266, "totalTokens": 895, "cost": 0.000163, "durationMs": 10547, "tokensPerSecond": 25.22, "toolCallCount": 0 }, { "questionId": "func-17", "category": "functions", "type": "mcq", "question": "Which environment variable is set at runtime to indicate how the function was triggered (e.g. http, event, schedule)?", "choices": [ "APPWRITE_TRIGGER_TYPE", "APPWRITE_FUNCTION_TRIGGER", "APPWRITE_EXECUTION_SOURCE", "APPWRITE_FUNCTION_EVENT" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 619, "completionTokens": 300, "totalTokens": 919, "cost": 0.000171, "durationMs": 36302, "tokensPerSecond": 8.26, "toolCallCount": 0 }, { "questionId": "func-18", "category": "functions", "type": "mcq", "question": "What are the deployment build statuses for an Appwrite Function?", "choices": [ "pending, building, ready", "processing, building, ready, and canceled", "queued, in_progress, success, failed", "uploaded, compiling, deployed" ], "correctAnswer": "B", "modelAnswer": "B", "correct": true, "score": 1, "promptTokens": 604, "completionTokens": 1978, "totalTokens": 2582, "cost": 0.000638, "durationMs": 24668, "tokensPerSecond": 80.18, "toolCallCount": 0 }, { "questionId": "func-19", "category": "functions", "type": "mcq", "question": "Which API key or auth type can be used to trigger a function execution (createExecution)?", "choices": [ "Only Server API key", "Only Session (logged-in user)", "Server API key, Session, scoped API key (Key), or JWT", "Only JWT" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 611, "completionTokens": 1165, "totalTokens": 1776, "cost": 0.000412, "durationMs": 26072, "tokensPerSecond": 44.68, "toolCallCount": 0 }, { "questionId": "func-20", "category": "functions", "type": "free-form", "question": "Name at least three APPWRITE_FUNCTION_* environment variables that are available inside an Appwrite Function at runtime, and what each is used for.", "correctAnswer": "Examples: APPWRITE_FUNCTION_ID (function ID), APPWRITE_FUNCTION_NAME, APPWRITE_FUNCTION_PROJECT_ID, APPWRITE_FUNCTION_API_ENDPOINT (for SDK), APPWRITE_FUNCTION_TRIGGER (http/event/schedule), APPWRITE_FUNCTION_EVENT (event name when event-triggered), APPWRITE_FUNCTION_JWT (user JWT when present), APPWRITE_FUNCTION_USER_ID, APPWRITE_FUNCTION_DATA / APPWRITE_FUNCTION_EVENT_DATA (body), APPWRITE_FUNCTION_DEPLOYMENT, APPWRITE_FUNCTION_RUNTIME_NAME, APPWRITE_FUNCTION_RUNTIME_VERSION, APPWRITE_FUNCTION_CPUS, APPWRITE_FUNCTION_MEMORY.", "rubric": "Must name at least 3 APPWRITE_FUNCTION_* variables with correct purpose. Accept any subset of the documented runtime env vars (ID, name, project ID, API endpoint, trigger, event, JWT, user ID, data, deployment, runtime, resources).", "modelAnswer": "Here are three `APPWRITE_FUNCTION_*` environment variables available inside an Appwrite Function at runtime, along with their specific use cases:\n\n1. **`APPWRITE_FUNCTION_TRIGGER`**\n - **What it is:** A string that indicates how the function was invoked.\n - **Use case:** Allows your function to branch its logic based on the trigger source. Common values include `http` (triggered by an HTTP request), `schedule` (triggered by a cron job), and `event` (triggered by an Appwrite system event, such as a document creation or update).\n\n2. **`APPWRITE_FUNCTION_EVENT_DATA`**\n - **What it is:** A JSON string containing the full payload of the event that triggered the function.\n - **Use case:** Essential for reacting to specific changes in Appwrite services. For example, if the function is triggered by a `databases.*.documents.create` event, this variable contains the newly created document’s data, allowing the function to process or validate it immediately.\n\n3. **`APPWRITE_FUNCTION_JWT`**\n - **What it is:** A JSON Web Token (JWT) representing the authenticated user who triggered the function (available when triggered via HTTP with a valid session or API key).\n - **Use case:** Enables the function to make authenticated API calls to other Appwrite services (e.g., Databases, Storage, or Messaging) on behalf of the triggering user. This ensures the function respects the user’s permissions and access levels when performing subsequent operations.", "correct": true, "score": 1, "judgeReasoning": "The model correctly identifies three valid APPWRITE_FUNCTION_* environment variables (APPWRITE_FUNCTION_TRIGGER, APPWRITE_FUNCTION_EVENT_DATA, and APPWRITE_FUNCTION_JWT) and provides accurate descriptions of their purposes. All three are documented runtime environment variables: TRIGGER indicates how the function was invoked (http/schedule/event), EVENT_DATA contains the event payload, and JWT provides the user's authentication token. The explanations are detailed and correct, meeting the rubric's requirement of naming at least 3 variables with correct purposes.", "promptTokens": 143, "completionTokens": 1957, "totalTokens": 2100, "cost": 0.000568, "durationMs": 23073, "tokensPerSecond": 84.82, "toolCallCount": 0 }, { "questionId": "stor-1", "category": "storage", "type": "mcq", "question": "What is a \"bucket\" in Appwrite Storage?", "choices": [ "A container for organizing and managing file uploads with shared permissions and settings", "A type of TablesDB table", "A caching layer for static assets", "A backup storage location" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 606, "completionTokens": 163, "totalTokens": 769, "cost": 0.00013, "durationMs": 3661, "tokensPerSecond": 44.52, "toolCallCount": 0 }, { "questionId": "stor-2", "category": "storage", "type": "mcq", "question": "How do you upload a file to Appwrite Storage?", "choices": [ "storage.createFile(bucketId, fileId, file)", "storage.upload()", "storage.putObject()", "files.create()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 588, "completionTokens": 239, "totalTokens": 827, "cost": 0.000149, "durationMs": 21275, "tokensPerSecond": 11.23, "toolCallCount": 0 }, { "questionId": "stor-3", "category": "storage", "type": "free-form", "question": "Write code using the Appwrite Web SDK to create a bucket, upload a file, and get a preview URL for an image file. Include permission configuration.", "correctAnswer": "Storage service provides createBucket() for bucket management, createFile() for uploads, and getFilePreview() for image transformations. Buckets support file size limits, allowed extensions, and permission configuration.", "rubric": "Must include: 1) Storage service instantiation, 2) Bucket creation with permissions, 3) storage.createFile() with bucket ID, file ID, and File object, 4) storage.getFilePreview() for image preview, 5) Correct imports", "modelAnswer": "Below is a complete example using the **Appwrite Web SDK** to create a storage bucket, upload an image file, and generate a preview URL. The code includes permission configuration for both the bucket and the uploaded file.\n\n```javascript\nimport { Client, Storage, Permission, Role, ID } from 'appwrite';\n\n// Initialize the Appwrite client (replace with your own endpoint and project ID)\nconst client = new Client()\n .setEndpoint('https://cloud.appwrite.io/v1') // Your Appwrite endpoint\n .setProject('YOUR_PROJECT_ID'); // Your project ID\n\nconst storage = new Storage(client);\n\n/**\n * Creates a bucket, uploads a file, and returns a preview URL.\n * @param {File} file - The image file to upload (e.g., from an element)\n * @returns {Promise} - The preview URL of the uploaded image\n */\nasync function createBucketAndUploadImage(file) {\n try {\n // 1. Create a new bucket with public read/write permissions\n const bucket = await storage.createBucket(\n ID.unique(), // Bucket ID (auto-generated)\n 'My Image Bucket', // Bucket name\n [\n Permission.read(Role.any()), // Anyone can read files\n Permission.write(Role.any()) // Anyone can upload files\n ],\n false, // File security (disabled for simplicity)\n true, // Enable bucket\n undefined, // Maximum file size (optional)\n undefined, // Allowed file extensions (optional)\n undefined, // Compression (optional)\n undefined, // Encryption (optional)\n undefined // Antivirus (optional)\n );\n\n const bucketId = bucket.$id;\n console.log(`Bucket created: ${bucketId}`);\n\n // 2. Upload the file with public read permission\n const uploadedFile = await storage.createFile(\n bucketId,\n ID.unique(), // File ID (auto-generated)\n file,\n [Permission.read(Role.any())] // File-level permission: public read\n );\n\n const fileId = uploadedFile.$id;\n console.log(`File uploaded: ${fileId}`);\n\n // 3. Get the preview URL (supports image transformations)\n const previewUrl = storage.getFilePreview(\n bucketId,\n fileId,\n 400, // Width (optional)\n 400, // Height (optional)\n 'center', // Gravity (optional)\n 100, // Quality (optional)\n 0, // Border width (optional)\n '', // Border color (optional)\n 0, // Border radius (optional)\n 0, // Opacity (optional)\n -360, // Rotation (optional)\n '', // Background color (optional)\n 'output.webp' // Output format (optional)\n );\n\n console.log(`Preview URL: ${previewUrl}`);\n return previewUrl;\n\n } catch (error) {\n console.error('Error:', error.message);\n throw error;\n }\n}\n\n// Example usage (assuming you have a file from an )\n// const fileInput = document.querySelector('input[type=\"file\"]');\n// fileInput.addEventListener('change', async (event) => {\n// const file = event.target.files[0];\n// if (file) {\n// const url = await createBucketAndUploadImage(file);\n// // Use the URL, e.g., set an src\n// document.querySelector('img').src = url;\n// }\n// });\n```\n\n### Key Points\n\n- **Permissions**:\n - Bucket-level: `Permission.read(Role.any())` and `Permission.write(Role.any())` allow anyone to read and upload files. In production, replace `Role.any()` with `Role.user('USER_ID')`, `Role.team('TEAM_ID')`, or `Role.guest()` as needed.\n - File-level: The uploaded file is given `Permission.read(Role.any())` so the preview URL is publicly accessible. You can omit this to inherit bucket permissions.\n\n- **Preview URL**: `getFilePreview` returns a URL that can be used directly in an `` tag. It supports optional transformations (width, height, quality, format, etc.). For a simple view URL without transformations, use `storage.getFileView(bucketId, fileId)`.\n\n- **Error Handling**: The `try/catch` block catches any Appwrite API errors (e.g., invalid permissions, quota exceeded).\n\n- **SDK Version**: This code uses the Appwrite Web SDK v1.x. Ensure you have installed it via `npm install appwrite` or included it via CDN.\n\nFor a production environment, always restrict permissions to the minimum required (e.g., only authenticated users can write, and only the file owner or specific roles can read).", "correct": true, "score": 1, "judgeReasoning": "The answer fully satisfies all five rubric requirements: 1) Storage service instantiation with `new Storage(client)`, 2) Bucket creation with permissions using `Permission.read(Role.any())` and `Permission.write(Role.any())`, 3) `storage.createFile()` called with bucket ID, file ID (`ID.unique()`), and File object, 4) `storage.getFilePreview()` for image preview with various transformation parameters, 5) Correct imports from 'appwrite' including Client, Storage, Permission, Role, and ID. The code is well-structured, includes error handling, and provides helpful explanations about permissions and usage.", "promptTokens": 143, "completionTokens": 1592, "totalTokens": 1735, "cost": 0.000466, "durationMs": 18086, "tokensPerSecond": 88.02, "toolCallCount": 0 }, { "questionId": "stor-4", "category": "storage", "type": "mcq", "question": "Which Appwrite Storage method provides image manipulation like resizing and cropping?", "choices": [ "storage.getFilePreview()", "storage.transformImage()", "storage.processImage()", "storage.getFileView()" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 582, "completionTokens": 241, "totalTokens": 823, "cost": 0.000149, "durationMs": 38805, "tokensPerSecond": 6.21, "toolCallCount": 0 }, { "questionId": "stor-5", "category": "storage", "type": "mcq", "question": "What parameters does getFilePreview() support for image transformation?", "choices": [ "Only width and height", "Only format conversion", "Width, height, gravity, quality, border, border-radius, opacity, rotation, background, and output format", "CSS filter strings" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 611, "completionTokens": 369, "totalTokens": 980, "cost": 0.000189, "durationMs": 8873, "tokensPerSecond": 41.59, "toolCallCount": 0 }, { "questionId": "stor-6", "category": "storage", "type": "mcq", "question": "How are file permissions handled in Appwrite Storage?", "choices": [ "Files can have individual permissions, or inherit from the bucket depending on fileSecurity setting", "All files in a bucket share the same permissions", "Permissions are only at the project level", "Files are always public" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 619, "completionTokens": 204, "totalTokens": 823, "cost": 0.000144, "durationMs": 5056, "tokensPerSecond": 40.35, "toolCallCount": 0 }, { "questionId": "stor-7", "category": "storage", "type": "mcq", "question": "What is the method to download a file from Appwrite Storage?", "choices": [ "storage.downloadFile()", "storage.fetchFile()", "storage.getFileDownload(bucketId, fileId)", "storage.read()" ], "correctAnswer": "C", "modelAnswer": "C", "correct": true, "score": 1, "promptTokens": 590, "completionTokens": 262, "totalTokens": 852, "cost": 0.000156, "durationMs": 8802, "tokensPerSecond": 29.77, "toolCallCount": 0 }, { "questionId": "stor-8", "category": "storage", "type": "mcq", "question": "Which bucket setting restricts the types of files that can be uploaded?", "choices": [ "allowedFileExtensions", "fileFilter", "mimeTypes", "uploadRestrictions" ], "correctAnswer": "A", "modelAnswer": "A", "correct": true, "score": 1, "promptTokens": 570, "completionTokens": 540, "totalTokens": 1110, "cost": 0.000231, "durationMs": 89161, "tokensPerSecond": 6.06, "toolCallCount": 0 }, { "questionId": "stor-9", "category": "storage", "type": "free-form", "question": "Explain the difference between storage.getFileView(), storage.getFileDownload(), and storage.getFilePreview(). When would you use each?", "correctAnswer": "getFileView() serves files inline for browser display. getFileDownload() triggers a download. getFilePreview() provides image transformation capabilities (resize, crop, format conversion). Only preview supports manipulation parameters.", "rubric": "Must explain: 1) getFileView() for inline/browser display, 2) getFileDownload() for triggering downloads, 3) getFilePreview() for image transformations, 4) When to use each one", "modelAnswer": "The core difference between these three methods lies in **how the file is served** to the client (the HTTP `Content-Disposition` header) and **whether the file is transformed** before being sent.\n\nHere is the breakdown:\n\n### 1. `getFileView()`\n- **Behavior:** Serves the file with the `Content-Disposition` header set to `inline`.\n- **Result:** The browser attempts to display the file directly within the browser window (e.g., rendering an image, playing a video, showing a PDF in a built-in viewer).\n- **When to use:**\n - Displaying images in a gallery or `` tag.\n - Embedding a PDF in an `