@harperfast/template-react-ts-studio 1.12.1 → 1.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/.agents/skills/harper-best-practices/AGENTS.md +672 -400
  2. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +131 -55
  3. package/.agents/skills/harper-best-practices/rules/checking-authentication.md +155 -61
  4. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +78 -48
  5. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
  6. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
  7. package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
  8. package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +108 -60
  9. package/.agents/skills/harper-best-practices/rules.manifest.yaml +212 -0
  10. package/agent/skills/harper-best-practices/AGENTS.md +672 -400
  11. package/agent/skills/harper-best-practices/rules/automatic-apis.md +131 -55
  12. package/agent/skills/harper-best-practices/rules/checking-authentication.md +155 -61
  13. package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +78 -48
  14. package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
  15. package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
  16. package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
  17. package/agent/skills/harper-best-practices/rules/v5-upgrade.md +108 -60
  18. package/agent/skills/harper-best-practices/rules.manifest.yaml +212 -0
  19. package/package.json +1 -1
  20. package/skills-lock.json +1 -1
@@ -5,17 +5,17 @@ metadata:
5
5
  mode: generate
6
6
  sources:
7
7
  - reference/v5/rest/querying.md
8
- sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
9
- inputHash: d5ed0e937cd2d7e0
8
+ sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
9
+ inputHash: 0f8efee293628a52
10
10
  ---
11
11
 
12
- # Querying Harper REST APIs
12
+ # Querying REST APIs
13
13
 
14
- Instructions for the agent to filter, sort, select, and paginate records using Harper's URL-based query language on REST collection endpoints.
14
+ Instructions for the agent to filter, sort, select, and paginate Harper REST API collections using URL query parameters.
15
15
 
16
16
  ## When to Use
17
17
 
18
- Apply this rule when building or debugging REST API calls against Harper tables that require filtering by attribute values, comparison ranges, sorting, field selection, or result pagination. This rule also covers OR logic, grouping, and querying across related tables via dot-syntax joins. See [automatic-apis.md](automatic-apis.md) for how Harper exposes tables as REST endpoints.
18
+ Apply this rule whenever building or modifying code that queries Harper REST collection endpoints. Use it when you need to filter records by attribute values, apply comparison operators, sort or paginate results, or join across related tables. See [automatic-apis.md](automatic-apis.md) for how Harper exposes tables as REST endpoints.
19
19
 
20
20
  ## How It Works
21
21
 
@@ -26,13 +26,7 @@ Apply this rule when building or debugging REST API calls against Harper tables
26
26
  GET /Product/?category=software&inStock=true
27
27
  ```
28
28
 
29
- 2. **Filter for null values**: Use `=null` as the value to match null or non-null records.
30
-
31
- ```
32
- GET /Product/?discount=null
33
- ```
34
-
35
- 3. **Apply comparison operators (FIQL syntax)**: Use FIQL operators in query parameters for range and string matching.
29
+ 2. **Apply comparison operators (FIQL syntax)**: Use FIQL operators in the query string for numeric, string, and date comparisons.
36
30
 
37
31
  | Operator | Meaning |
38
32
  | -------------------- | -------------------------------------- |
@@ -61,13 +55,13 @@ Apply this rule when building or debugging REST API calls against Harper tables
61
55
  GET /Product/?listDate=gt=2017-03-08T09%3A30%3A00.000Z
62
56
  ```
63
57
 
64
- 4. **Chain conditions for range queries**: Omit the attribute name on the second condition to apply it to the same attribute. Only `gt`/`ge` combined with `lt`/`le` is supported for chaining.
58
+ 3. **Chain conditions for range queries**: Omit the attribute name on the second condition to apply it to the same attribute. Only `gt`/`ge` combined with `lt`/`le` is supported.
65
59
 
66
60
  ```
67
61
  GET /Product/?price=gt=100&lt=200
68
62
  ```
69
63
 
70
- 5. **Apply type conversion**: For FIQL comparators, Harper converts values automatically. Use explicit prefixes to force a type.
64
+ 4. **Apply type conversion**: For FIQL comparators, Harper converts values automatically. Use explicit prefixes to force a type.
71
65
 
72
66
  | Syntax | Behavior |
73
67
  | ----------------------------------------- | ------------------------------------------- |
@@ -81,32 +75,26 @@ Apply this rule when building or debugging REST API calls against Harper tables
81
75
 
82
76
  For strict operators (`=`, `===`, `!==`), no automatic type conversion is applied.
83
77
 
84
- 6. **Combine conditions with OR logic**: Use `|` instead of `&` to express OR between conditions.
78
+ 5. **Combine conditions with OR logic**: Use `|` instead of `&`.
85
79
 
86
80
  ```
87
81
  GET /Product/?rating=5|featured=true
88
82
  ```
89
83
 
90
- 7. **Group conditions**: Use parentheses or square brackets to control evaluation order. Prefer square brackets when building queries from user input, since `[` and `]` are safely URI-encoded.
84
+ 6. **Group conditions**: Use parentheses or square brackets to control order of operations. Prefer square brackets when constructing queries from user input, since standard URI encoding safely encodes `[` and `]`.
91
85
 
92
86
  ```
93
87
  GET /Product/?rating=5|(price=gt=100&price=lt=200)
94
88
  GET /Product/?rating=5&[tag=fast|tag=scalable|tag=efficient]
95
89
  ```
96
90
 
97
- Build grouped queries in JavaScript:
91
+ Construct from JavaScript:
98
92
 
99
93
  ```javascript
100
94
  let url = `/Product/?rating=5&[${tags.map(encodeURIComponent).join('|')}]`;
101
95
  ```
102
96
 
103
- Nest groups for complex conditions:
104
-
105
- ```
106
- GET /Product/?price=lt=100|[rating=5&[tag=fast|tag=scalable|tag=efficient]&inStock=true]
107
- ```
108
-
109
- 8. **Select specific properties with `select(`**: Append `select(...)` as a query function separated by `&` to control which fields are returned.
97
+ 7. **Select specific properties with `select(`**: Append `select(...)` as a query function separated by `&`.
110
98
 
111
99
  | Syntax | Returns |
112
100
  | -------------------------------------- | ------------------------------------------- |
@@ -116,65 +104,47 @@ Apply this rule when building or debugging REST API calls against Harper tables
116
104
  | `?select(property1,)` | Objects with a single specified property |
117
105
  | `?select(property{subProp1,subProp2})` | Nested objects with specific sub-properties |
118
106
 
119
- ```
120
- GET /Product/?category=software&select(name)
121
- GET /Product/?brand.name=Microsoft&select(name,brand{name})
122
- ```
107
+ 8. **Paginate with `limit(`**: Use `limit(end)` or `limit(start,end)` to control result count and offset.
123
108
 
124
- 9. **Paginate results with `limit(`**: Use `limit(end)` or `limit(start,end)` to restrict the number of records returned.
109
+ 9. **Sort with `sort(`**: Use `sort(property)` or `sort(+property,-property,...)`. Prefix `+` or no prefix = ascending; `-` = descending.
125
110
 
126
- ```
127
- GET /Product/?rating=gt=3&inStock=true&select(rating,name)&limit(20)
128
- GET /Product/?rating=gt=3&limit(10,30)
129
- ```
111
+ 10. **Query across relationships**: Use dot-syntax to filter by related table attributes. Relationships must be defined in the schema using `@relationship`. Relationship attributes are not included by default — use `select()` to include them.
130
112
 
131
- 10. **Sort results with `sort(`**: Use `sort(property)` or `sort(+property,-property,...)` to order results. Prefix `+` or no prefix = ascending; `-` = descending.
132
-
133
- ```
134
- GET /Product/?rating=gt=3&sort(+name)
135
- GET /Product/?sort(+rating,-price)
136
- ```
137
-
138
- 11. **Query across relationships using dot-syntax**: Filter on related table attributes using dot-chained property names. Relationships must be defined in the schema with `@relationship`.
139
-
140
- ```
141
- GET /Product/?brand.name=Microsoft
142
- GET /Brand/?products.name=Keyboard
143
113
  ```
144
-
145
- Use `select()` to include relationship attributes in the response (they are excluded by default):
146
-
147
- ```
148
- GET /Product/?brand.name=Microsoft&select(name,brand)
149
114
  GET /Product/?brand.name=Microsoft&select(name,brand{name})
150
115
  ```
151
116
 
152
- 12. **Access a specific property by URL**: Append `.propertyName` to a record ID in the URL path. Only works for properties declared in the schema.
117
+ 11. **Query for null values**: Use `=null` as the value to match null or non-null records.
153
118
  ```
154
- GET /MyTable/123.propertyName
119
+ GET /Product/?discount=null
155
120
  ```
156
121
 
157
122
  ## Examples
158
123
 
159
- **Range filter with select and limit**:
124
+ **Filter with comparison operators and select:**
160
125
 
161
126
  ```
162
- GET /Product/?category=software&price=gt=100&price=lt=200&select(name,price)&limit(20)
127
+ GET /Product/?category=software&price=gt=100&price=lt=200&select(name,price)
163
128
  ```
164
129
 
165
- **Sort and paginate**:
130
+ **Paginate and sort:**
166
131
 
167
132
  ```
168
- GET /Product/?rating=gt=3&sort(+rating,-price)&limit(10,30)
133
+ GET /Product/?rating=gt=3&inStock=true&select(rating,name)&limit(20)
134
+ GET /Product/?rating=gt=3&limit(10,30)
135
+ GET /Product/?rating=gt=3&sort(+name)
136
+ GET /Product/?sort(+rating,-price)
169
137
  ```
170
138
 
171
- **OR with grouping**:
139
+ **OR logic with grouping:**
172
140
 
173
141
  ```
174
142
  GET /Product/?price=lt=100|[rating=5&[tag=fast|tag=scalable|tag=efficient]&inStock=true]
175
143
  ```
176
144
 
177
- **Join query with nested select** — schema first:
145
+ **Relationship join with nested select:**
146
+
147
+ Define the schema:
178
148
 
179
149
  ```graphql
180
150
  type Product @table @export {
@@ -190,13 +160,14 @@ type Brand @table @export {
190
160
  }
191
161
  ```
192
162
 
193
- Then query:
163
+ Query with join:
194
164
 
195
165
  ```
196
166
  GET /Product/?brand.name=Microsoft&select(name,brand{name,id})
167
+ GET /Brand/?products.name=Keyboard
197
168
  ```
198
169
 
199
- **Many-to-many relationship** — schema:
170
+ **Many-to-many relationship:**
200
171
 
201
172
  ```graphql
202
173
  type Product @table @export {
@@ -207,23 +178,20 @@ type Product @table @export {
207
178
  }
208
179
  ```
209
180
 
210
- Query:
211
-
212
181
  ```
213
182
  GET /Product/?resellers.name=Cool Shop&select(id,name,resellers{name,id})
214
183
  ```
215
184
 
216
- **Date range with URL-encoded colons**:
185
+ **Access a specific property by record ID:**
217
186
 
218
187
  ```
219
- GET /Product/?listDate=gt=2017-03-08T09%3A30%3A00.000Z
188
+ GET /MyTable/123.propertyName
220
189
  ```
221
190
 
222
191
  ## Notes
223
192
 
224
- - All filtered attributes must be indexed unless at least one other attribute in the same query is indexed.
225
- - Null queries (`?attr=null`) require indexes created after null indexing support was added. Rebuild existing indexes (remove and re-add) to enable null queries on them.
226
- - When selecting a related attribute without filtering on it, the join behaves as a LEFT JOIN — the relationship property is omitted if the foreign key is null or references a non-existent record.
227
- - The array order of foreign key values (e.g., `resellerIds`) is preserved when resolving many-to-many relationships.
228
- - Square brackets (`[`, `]`) are preferred over parentheses for grouping when constructing queries programmatically, because standard URI encoding safely encodes them.
229
- - `directURLMapping: true` can be set on a resource to change URL path handling semantics; see your schema configuration for details.
193
+ - Only indexed attributes can be used as the primary filter attribute; when combining multiple attributes, only one needs to be indexed.
194
+ - Relationship attributes are excluded from responses by default. Always use `select(` to include them.
195
+ - When selecting a related attribute without filtering on it, the behavior is a LEFT JOIN — the property is omitted if the foreign key is null or references a non-existent record.
196
+ - The suffixes `.json`, `.cbor`, `.msgpack`, and `.csv` in URL paths are reserved as content-type selectors and take precedence over a property of the same name.
197
+ - Square brackets are preferred over parentheses when building grouped queries programmatically, because `[` and `]` are safely URL-encoded by standard encoding functions while `(` is not.
@@ -9,21 +9,32 @@ metadata:
9
9
  - reference/v5/database/schema.md#Overview
10
10
  - reference/v5/database/schema.md#Type Directives
11
11
  - reference/v5/database/schema.md#Field Directives
12
- sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
13
- inputHash: ce22f3fefb660c6e
12
+ sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
13
+ inputHash: ecb06058191ba29f
14
14
  ---
15
15
 
16
16
  # Schema Design and GraphQL Tooling
17
17
 
18
- Instructions for the agent to follow when designing Harper schemas, applying core directives, and configuring GraphQL tooling.
18
+ Instructions for the agent to follow when designing Harper database schemas using GraphQL type definitions, core directives, and tooling configuration.
19
19
 
20
20
  ## When to Use
21
21
 
22
- Apply this rule when creating or modifying Harper schema files (`.graphql`), configuring `graphqlSchema` in `config.yaml`, or deciding which directives to apply to types and fields. Use it any time you need to define tables, primary keys, indexes, or exported endpoints.
22
+ Apply this rule when creating or modifying Harper schema files (`.graphql`), configuring schema loading in `config.yaml`, or deciding which directives to apply to tables and fields. Use it whenever a task involves defining tables, primary keys, indexes, or export behavior.
23
23
 
24
24
  ## How It Works
25
25
 
26
- 1. **Declare the schema file** in the component's `config.yaml` using the `graphqlSchema` plugin:
26
+ 1. **Create a GraphQL schema file** with Harper-specific directives. Schemas ensure required tables exist on deployment, enforce types and constraints, control indexing, and define relationships.
27
+
28
+ ```graphql
29
+ type Dog @table {
30
+ id: Long @primaryKey
31
+ name: String
32
+ breed: String
33
+ age: Int
34
+ }
35
+ ```
36
+
37
+ 2. **Register the schema in `config.yaml`** using the `graphqlSchema` plugin:
27
38
 
28
39
  ```yaml
29
40
  graphqlSchema:
@@ -32,76 +43,74 @@ Apply this rule when creating or modifying Harper schema files (`.graphql`), con
32
43
 
33
44
  Both plugins and applications can specify schemas.
34
45
 
35
- 2. **Mark types as tables** with `@table`. The type name becomes the table name by default:
46
+ 3. **Mark each type as a table** with `@table`. The type name becomes the table name by default.
36
47
 
37
48
  ```graphql
38
- type Dog @table {
49
+ type MyTable @table {
39
50
  id: Long @primaryKey
40
- name: String
41
- breed: String
42
- age: Int
43
51
  }
44
52
  ```
45
53
 
46
- 3. **Set a primary key** on every table using `@primaryKey`. Primary keys must be unique; duplicate-key inserts are rejected. If no primary key is provided on insert, Harper auto-generates one based on the field type:
47
- - `String` or `ID` → UUID string
48
- - `Int`, `Long`, or `Any` → auto-incrementing integer
54
+ Key `@table` arguments:
49
55
 
50
- Use `Long` or `Any` for auto-generated numeric keys; `Int` is 32-bit and may be insufficient for large tables.
56
+ | Argument | Type | Default | Description |
57
+ | -------------------- | --------- | ----------------------------- | --------------------------------------------------------------- |
58
+ | `table` | `String` | type name | Override the table name |
59
+ | `database` | `String` | `"data"` | Database to place the table in |
60
+ | `expiration` | `Int` | — | Seconds until a record goes stale |
61
+ | `eviction` | `Int` | `0` | Additional seconds after `expiration` before physical removal |
62
+ | `scanInterval` | `Int` | `(expiration + eviction) / 4` | Seconds between eviction scans |
63
+ | `replicate` | `Boolean` | `true` | Enable replication of this table |
64
+ | `cacheControl` | `String` | — | `Cache-Control` header for anonymous GET/HEAD 200/304 responses |
65
+ | `randomAccessFields` | `Boolean` | `storage.randomAccessFields` | Pin this table's record encoding |
66
+
67
+ 4. **Designate a primary key** on every table using `@primaryKey`. Primary keys must be unique; duplicate inserts are rejected. If no primary key is provided on insert, Harper auto-generates one:
68
+ - **UUID string** — when type is `String` or `ID`
69
+ - **Auto-incrementing integer** — when type is `Int`, `Long`, or `Any`
51
70
 
52
- 4. **Index fields for querying** with `@indexed`. Required for filtering by an attribute in REST queries, SQL, or NoSQL operations:
71
+ Use `Long` or `Any` for auto-generated numeric keys; `Int` is 32-bit and may be insufficient for large tables.
53
72
 
54
73
  ```graphql
55
- type Breed @table {
74
+ type Product @table {
56
75
  id: Long @primaryKey
57
- name: String @indexed
76
+ name: String
58
77
  }
59
78
  ```
60
79
 
61
- If the field value is an array, each element is individually indexed. Null values are indexed by default.
62
-
63
- 5. **Expose a table as an external endpoint** with `@export`. Available via REST, MQTT, and other interfaces. The optional `name` parameter sets the URL path segment:
80
+ 5. **Add secondary indexes** with `@indexed` on any attribute that will be used for filtering in REST queries, SQL, or NoSQL operations. If the field value is an array, each element is individually indexed.
64
81
 
65
82
  ```graphql
66
- type MyTable @table @export(name: "my-table") {
83
+ type Product @table {
67
84
  id: Long @primaryKey
85
+ category: String @indexed
86
+ price: Float @indexed
68
87
  }
69
88
  ```
70
89
 
71
- Without `name`, the type name is used.
72
-
73
- 6. **Configure `@table` arguments** as needed. All arguments are optional:
74
-
75
- | Argument | Type | Default | Description |
76
- | -------------- | --------- | ----------------------------- | ------------------------------------------------------------- |
77
- | `table` | `String` | type name | Override the table name |
78
- | `database` | `String` | `"data"` | Database to place the table in |
79
- | `expiration` | `Int` | — | Seconds until a record goes stale |
80
- | `eviction` | `Int` | `0` | Additional seconds after `expiration` before physical removal |
81
- | `scanInterval` | `Int` | `(expiration + eviction) / 4` | Seconds between eviction scans |
82
- | `replicate` | `Boolean` | `true` | Enable replication of this table |
83
-
84
- 7. **Apply additional field directives** where needed:
85
- - `@createdTime` — auto-assigns creation timestamp (Unix epoch ms)
86
- - `@updatedTime` — auto-assigns update timestamp (Unix epoch ms)
87
- - `@expiresAt` — marks a field as the record's absolute expiration time (Unix epoch ms)
88
- - `@embed(source:, model:)` — computes an embedding vector when the source field is written; field type must be `[Float]`
89
- - `@hidden` — suppresses the field from MCP tool descriptors and OpenAPI document (not an access-control mechanism)
90
-
91
- 8. **Use `@sealed`** on a type to prevent records from including properties beyond those declared in the schema:
90
+ 6. **Expose tables via REST and other interfaces** using `@export`. Without `@export`, the table has no REST/MQTT route (callers get 404). The optional `name` parameter sets the URL path segment.
92
91
 
93
92
  ```graphql
94
- type StrictRecord @table @sealed {
93
+ type MyTable @table @export(name: "my-table") {
95
94
  id: Long @primaryKey
96
- name: String
97
95
  }
98
96
  ```
99
97
 
100
- 9. **Use unique database names** in plugins or applications to avoid table naming collisions, since all tables default to the `data` database.
98
+ `@export` is a routing directive, not access control. The table remains accessible through the Operations API and SQL regardless. REST must also be enabled for the application (via `rest: true` in `config.yaml` or Harper's built-in default).
99
+
100
+ 7. **Apply additional type directives** as needed:
101
+ - `@sealed` — prevents records from including properties beyond those declared in the schema.
102
+ - `@hidden` — suppresses the type from MCP tool descriptors and the OpenAPI document. Does not restrict data access.
103
+
104
+ 8. **Apply field directives** for computed and lifecycle behavior:
105
+ - `@createdTime` — assigns Unix epoch milliseconds on record creation.
106
+ - `@updatedTime` — assigns Unix epoch milliseconds on each update.
107
+ - `@expiresAt` — marks a field as the record's absolute expiration time (Unix epoch milliseconds); authoritative over the table-level `expiration` default.
108
+ - `@embed` — computes an embedding vector when the source field is written (requires `source` and `model` arguments; field type must be `[Float]`).
109
+ - `@hidden` (field) — suppresses the field from generated specs and MCP tool schemas; does not restrict data access.
101
110
 
102
111
  ## Examples
103
112
 
104
- **Minimal schema with two tables:**
113
+ **Minimal two-table schema:**
105
114
 
106
115
  ```graphql
107
116
  type Dog @table {
@@ -127,56 +136,59 @@ type WeatherCache @table(expiration: 300, eviction: 3300, scanInterval: 600) {
127
136
  }
128
137
  ```
129
138
 
130
- **Table with multiple `@table` arguments combined:**
139
+ **Exported table with cache control:**
131
140
 
132
141
  ```graphql
133
- type Event @table(database: "analytics", expiration: 86400) {
142
+ type Product @table(cacheControl: "public, max-age=60") @export {
134
143
  id: Long @primaryKey
135
- name: String @indexed
144
+ name: String
145
+ price: Float
136
146
  }
137
147
  ```
138
148
 
139
- **Exported table with overridden table name:**
149
+ **Table with lifecycle fields and indexing:**
140
150
 
141
151
  ```graphql
142
- type Product @table(table: "products") @export(name: "products") {
152
+ type Event @table(database: "analytics", expiration: 86400) {
143
153
  id: Long @primaryKey
144
- category: String @indexed
145
- price: Float @indexed
154
+ name: String @indexed
155
+ createdAt: Long @createdTime
156
+ updatedAt: Long @updatedTime
146
157
  }
147
158
  ```
148
159
 
149
- **Table with timestamps and per-record expiration:**
160
+ **Session table with per-record expiration:**
150
161
 
151
162
  ```graphql
152
163
  type Session @table {
153
164
  id: ID @primaryKey
154
165
  token: String
155
- createdAt: Long @createdTime
156
- updatedAt: Long @updatedTime
157
166
  expiresAt: Long @expiresAt
158
167
  }
159
168
  ```
160
169
 
161
- **Table with a hidden internal field:**
170
+ **Sealed table preventing extra properties:**
162
171
 
163
172
  ```graphql
164
- type Customer @table {
173
+ type StrictRecord @table @sealed {
165
174
  id: Long @primaryKey
166
175
  name: String
167
-
168
- """
169
- Internal — do not surface to external consumers.
170
- """
171
- creditScore: Int @hidden
172
176
  }
173
177
  ```
174
178
 
179
+ **`config.yaml` schema registration:**
180
+
181
+ ```yaml
182
+ graphqlSchema:
183
+ files: 'schema.graphql'
184
+ ```
185
+
175
186
  ## Notes
176
187
 
177
- - `@table`, `@export`, `@sealed`, and `@hidden` are type-level directives; `@primaryKey`, `@indexed`, `@embed`, `@createdTime`, `@updatedTime`, `@expiresAt`, and `@hidden` are field-level directives.
178
- - `eviction` removes non-indexed record data but does **not** remove a record from its secondary indexes. Indexes remain functional for evicted records; Harper fetches the full record on demand when a query matches an evicted entry.
179
- - `scanInterval` is clock-aligned to the server's local timezone, not startup-aligned. The server's startup time does not affect when eviction runs.
180
- - Replication is enabled by default. If you disable replication on a table and re-enable it later, it will not catch up on writes made while replication was disabled.
181
- - `@hidden` is a metadata-visibility directive only. Use `attribute_permissions` on roles to enforce data access control.
182
- - A full-record `put` that omits an `@expiresAt` field clears it; a `patch` of other fields preserves it.
188
+ - Schemas are flexible by default — records may include additional properties beyond those declared. Use `@sealed` to prevent this.
189
+ - Use unique `database` names in plugins or applications to avoid table naming collisions, since all tables default to the `"data"` database.
190
+ - Replication is enabled by default. If you disable replication and re-enable it later, the table will not catch up on writes made while replication was disabled.
191
+ - `@hidden` (type or field) is a metadata-visibility directive only. Use table-level role permissions and `attribute_permissions` whitelists to restrict actual data access.
192
+ - `@export` absence causes 404 on REST/MQTT routes but does not protect data from the Operations API or SQL.
193
+ - The `cacheControl` argument emits headers only on anonymous (unauthenticated) GET/HEAD 200/304 responses. Authenticated responses receive `Cache-Control: private, no-cache`.
194
+ - `randomAccessFields` on `@table` pins the record encoding at table creation time. Editing the argument later does not repin an existing table.