Skip to content

Commit 1a2edba

Browse files
committed
fix(conformance): correct test fixtures — field names, prefixes, type consistency
acl_evaluation.json: - Fix condition field names: role→roles (list), identity_type→identity_types (list), call_depth.lte→max_call_depth (integer) to match spec §6.3 - Rename compound test IDs for clarity (compound_or_match→compound_or_in_callers) - Add $or/$not compound condition tests (in conditions dict, not just callers) - Add edge cases: empty callers/targets, @System pattern, conditions without context error_codes.json: - Remove phantom prefixes INTERNAL_, INVALID_ (not in spec) - Fix FUNC_MISSING_→FUNC_ (correct granularity) - Add missing prefixes: GENERAL_, EXECUTION_, RELOAD_, DEPENDENCY_ - Add test case for GENERAL_ prefix collision config_env.json: - Make all expected_value strings (env vars are always strings; coercion is separate) - Add description clarifying scope (path mapping only, not coercion) context_serialization.json: - Standardize to use expected field consistently - Restructure identity_all_types as sub_cases - Add redacted_inputs serialization test case schema_validation.json: - Fix empty_schema description (Draft 2020-12: always-true, not type:object) - Add empty_schema_accepts_string test to prove any-type behavior - Add expected_error_path to invalid test cases version_negotiation.json: - Change ValueError→PARSE_ERROR (language-agnostic) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> Signed-off-by: tercel <[email protected]>
1 parent 7865de6 commit 1a2edba

File tree

6 files changed

+232
-84
lines changed

6 files changed

+232
-84
lines changed

conformance/fixtures/acl_evaluation.json

Lines changed: 117 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "ACL rule evaluation (first-match-wins)",
2+
"description": "ACL rule evaluation (first-match-wins, spec §6)",
33
"test_cases": [
44
{
55
"id": "allow_rule_match",
@@ -81,7 +81,8 @@
8181
"expected": true
8282
},
8383
{
84-
"id": "compound_or_match",
84+
"id": "compound_or_in_callers",
85+
"description": "$or as first element in callers array — matches if any subsequent pattern matches",
8586
"rules": [
8687
{
8788
"callers": ["$or", "admin", "moderator"],
@@ -95,7 +96,8 @@
9596
"expected": true
9697
},
9798
{
98-
"id": "compound_not_match",
99+
"id": "compound_not_in_callers",
100+
"description": "$not as first element in callers array — matches if subsequent pattern does NOT match",
99101
"rules": [
100102
{
101103
"callers": ["$not", "banned_user"],
@@ -109,32 +111,34 @@
109111
"expected": true
110112
},
111113
{
112-
"id": "condition_role_match",
114+
"id": "condition_roles_match",
115+
"description": "conditions.roles (list) — at least one role must overlap with identity roles",
113116
"rules": [
114117
{
115118
"callers": ["*"],
116119
"targets": ["*"],
117120
"effect": "allow",
118121
"conditions": {
119-
"role": "editor"
122+
"roles": ["editor"]
120123
}
121124
}
122125
],
123126
"default_effect": "deny",
124127
"caller_id": "user_123",
125-
"caller_identity": {"type": "user", "roles": ["editor"]},
128+
"caller_identity": {"type": "user", "roles": ["editor", "viewer"]},
126129
"target_id": "posts.edit",
127130
"expected": true
128131
},
129132
{
130-
"id": "condition_role_mismatch",
133+
"id": "condition_roles_mismatch",
134+
"description": "conditions.roles — no overlap with identity roles",
131135
"rules": [
132136
{
133137
"callers": ["*"],
134138
"targets": ["*"],
135139
"effect": "allow",
136140
"conditions": {
137-
"role": "admin"
141+
"roles": ["admin"]
138142
}
139143
}
140144
],
@@ -145,14 +149,15 @@
145149
"expected": false
146150
},
147151
{
148-
"id": "condition_identity_type_match",
152+
"id": "condition_identity_types_match",
153+
"description": "conditions.identity_types (list) — identity type must be in allowed list",
149154
"rules": [
150155
{
151156
"callers": ["*"],
152157
"targets": ["*"],
153158
"effect": "allow",
154159
"conditions": {
155-
"identity_type": "service"
160+
"identity_types": ["service"]
156161
}
157162
}
158163
],
@@ -163,14 +168,15 @@
163168
"expected": true
164169
},
165170
{
166-
"id": "condition_call_depth_match",
171+
"id": "condition_max_call_depth_match",
172+
"description": "conditions.max_call_depth (integer) — call depth must not exceed threshold",
167173
"rules": [
168174
{
169175
"callers": ["*"],
170176
"targets": ["*"],
171177
"effect": "allow",
172178
"conditions": {
173-
"call_depth": {"lte": 2}
179+
"max_call_depth": 2
174180
}
175181
}
176182
],
@@ -181,14 +187,15 @@
181187
"expected": true
182188
},
183189
{
184-
"id": "condition_call_depth_mismatch",
190+
"id": "condition_max_call_depth_exceeded",
191+
"description": "conditions.max_call_depth — call depth exceeds threshold",
185192
"rules": [
186193
{
187194
"callers": ["*"],
188195
"targets": ["*"],
189196
"effect": "allow",
190197
"conditions": {
191-
"call_depth": {"lte": 1}
198+
"max_call_depth": 1
192199
}
193200
}
194201
],
@@ -197,6 +204,102 @@
197204
"call_depth": 2,
198205
"target_id": "mod_c",
199206
"expected": false
207+
},
208+
{
209+
"id": "empty_callers_matches_none",
210+
"description": "Empty callers array never matches any caller",
211+
"rules": [
212+
{"callers": [], "targets": ["*"], "effect": "allow"}
213+
],
214+
"default_effect": "deny",
215+
"caller_id": "anyone",
216+
"target_id": "anything",
217+
"expected": false
218+
},
219+
{
220+
"id": "empty_targets_matches_none",
221+
"description": "Empty targets array never matches any target",
222+
"rules": [
223+
{"callers": ["*"], "targets": [], "effect": "allow"}
224+
],
225+
"default_effect": "deny",
226+
"caller_id": "anyone",
227+
"target_id": "anything",
228+
"expected": false
229+
},
230+
{
231+
"id": "at_system_pattern",
232+
"description": "@system matches calls where identity type is system",
233+
"rules": [
234+
{"callers": ["@system"], "targets": ["*"], "effect": "allow"}
235+
],
236+
"default_effect": "deny",
237+
"caller_id": "system.health",
238+
"caller_identity": {"type": "system"},
239+
"target_id": "internal.check",
240+
"expected": true
241+
},
242+
{
243+
"id": "conditions_without_context_denies",
244+
"description": "Conditions present but no context provided — rule does not match",
245+
"rules": [
246+
{
247+
"callers": ["*"],
248+
"targets": ["*"],
249+
"effect": "allow",
250+
"conditions": {
251+
"roles": ["admin"]
252+
}
253+
}
254+
],
255+
"default_effect": "deny",
256+
"caller_id": "user_123",
257+
"caller_identity": null,
258+
"target_id": "admin.panel",
259+
"expected": false
260+
},
261+
{
262+
"id": "condition_or_compound",
263+
"description": "$or in conditions — matches if any sub-condition set passes",
264+
"rules": [
265+
{
266+
"callers": ["*"],
267+
"targets": ["*"],
268+
"effect": "allow",
269+
"conditions": {
270+
"$or": [
271+
{"roles": ["admin"]},
272+
{"identity_types": ["system"]}
273+
]
274+
}
275+
}
276+
],
277+
"default_effect": "deny",
278+
"caller_id": "sys_agent",
279+
"caller_identity": {"type": "system", "roles": []},
280+
"target_id": "admin.panel",
281+
"expected": true
282+
},
283+
{
284+
"id": "condition_not_compound",
285+
"description": "$not in conditions — matches if sub-condition set fails",
286+
"rules": [
287+
{
288+
"callers": ["*"],
289+
"targets": ["*"],
290+
"effect": "allow",
291+
"conditions": {
292+
"$not": {
293+
"identity_types": ["anonymous"]
294+
}
295+
}
296+
}
297+
],
298+
"default_effect": "deny",
299+
"caller_id": "user_123",
300+
"caller_identity": {"type": "user", "roles": []},
301+
"target_id": "protected.resource",
302+
"expected": true
200303
}
201304
]
202305
}
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "Environment variable to Config path mapping (Algorithm A12-NS)",
2+
"description": "Environment variable to Config path mapping (Algorithm A12-NS, spec §9.8). Tests path resolution and prefix matching only — type coercion is tested separately in schema_validation.json.",
33
"namespaces": [
44
{
55
"name": "observability",
@@ -30,97 +30,97 @@
3030
{
3131
"id": "global_mapped_variable_port",
3232
"env_var": "PORT",
33+
"env_value": "8080",
3334
"expected_path": "server.port",
34-
"expected_value": 8080,
35-
"env_value": "8080"
35+
"expected_value": "8080"
3636
},
3737
{
3838
"id": "global_mapped_variable_db",
3939
"env_var": "DATABASE_URL",
40+
"env_value": "sqlite:///data.db",
4041
"expected_path": "storage.database_url",
41-
"expected_value": "sqlite:///data.db",
42-
"env_value": "sqlite:///data.db"
42+
"expected_value": "sqlite:///data.db"
4343
},
4444
{
4545
"id": "global_mapped_variable_debug",
4646
"env_var": "DEBUG",
47+
"env_value": "DEBUG",
4748
"expected_path": "logging.level",
48-
"expected_value": "DEBUG",
49-
"env_value": "DEBUG"
49+
"expected_value": "DEBUG"
5050
},
5151
{
5252
"id": "exact_prefix_match",
5353
"env_var": "APCORE_OBSERVABILITY_TRACING_ENABLED",
54+
"env_value": "true",
5455
"expected_path": "observability.tracing.enabled",
55-
"expected_value": "true",
56-
"env_value": "true"
56+
"expected_value": "true"
5757
},
5858
{
5959
"id": "nested_path_match",
6060
"env_var": "APCORE_MCP_ROUTER_MAX_TIMEOUT",
61+
"env_value": "30000",
6162
"expected_path": "mcp.router.max_timeout",
62-
"expected_value": 30000,
63-
"env_value": "30000"
63+
"expected_value": "30000"
6464
},
6565
{
6666
"id": "longest_prefix_rule",
6767
"env_var": "APCORE_SYS_MODULES_RELOAD_ENABLED",
68+
"env_value": "false",
6869
"expected_path": "sys.modules.reload.enabled",
69-
"expected_value": "false",
70-
"env_value": "false"
70+
"expected_value": "false"
7171
},
7272
{
7373
"id": "global_prefix_fallback",
7474
"env_var": "APCORE_EXECUTOR_TIMEOUT",
75+
"env_value": "5000",
7576
"expected_path": "executor.timeout",
76-
"expected_value": "5000",
77-
"env_value": "5000"
77+
"expected_value": "5000"
7878
},
7979
{
8080
"id": "unknown_prefix_ignore",
8181
"env_var": "MY_APP_DEBUG",
82+
"env_value": "true",
8283
"expected_path": null,
83-
"expected_value": null,
84-
"env_value": "true"
84+
"expected_value": null
8585
},
8686
{
8787
"id": "ambiguous_prefix_resolution",
8888
"env_var": "APCORE_OBSERVABILITY_LEVEL",
89+
"env_value": "debug",
8990
"expected_path": "observability.level",
90-
"expected_value": "debug",
91-
"env_value": "debug"
91+
"expected_value": "debug"
9292
},
9393
{
9494
"id": "env_style_nested",
9595
"env_style": "nested",
9696
"env_var": "APCORE_MCP__SERVER__PORT",
97+
"env_value": "9000",
9798
"expected_path": "mcp.server.port",
98-
"expected_value": 9000,
99-
"env_value": "9000"
99+
"expected_value": "9000"
100100
},
101101
{
102102
"id": "env_style_flat",
103103
"env_style": "flat",
104104
"env_var": "APCORE_MCP_SERVER_PORT",
105+
"env_value": "9000",
105106
"expected_path": "mcp.server.port",
106-
"expected_value": 9000,
107-
"env_value": "9000"
107+
"expected_value": "9000"
108108
},
109109
{
110110
"id": "env_style_auto_detect_nested",
111111
"env_style": "auto",
112112
"env_var": "APCORE_MCP__SERVER__PORT",
113+
"env_value": "9000",
113114
"expected_path": "mcp.server.port",
114-
"expected_value": 9000,
115-
"env_value": "9000"
115+
"expected_value": "9000"
116116
},
117117
{
118118
"id": "env_style_auto_detect_flat",
119119
"env_style": "auto",
120120
"env_var": "APCORE_MCP_SERVER_PORT",
121+
"env_value": "9000",
121122
"expected_path": "mcp.server.port",
122-
"expected_value": 9000,
123-
"env_value": "9000"
123+
"expected_value": "9000"
124124
}
125125
]
126126
}

0 commit comments

Comments
 (0)