@ebowwa/logic-spec 1.0.0

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.
package/SPEC.md ADDED
@@ -0,0 +1,783 @@
1
+ # Logic Specification (logic.yaml) v1.0
2
+
3
+ A language-agnostic standard for extracting pure logic from implementations.
4
+
5
+ ## Overview
6
+
7
+ `logic.yaml` captures the **what** and **how** of a system's behavior without the **syntax** of any particular language. This enables:
8
+
9
+ - AI agents to understand logic without reading implementation code
10
+ - Portability across languages and runtimes
11
+ - Automated validation, testing, and documentation generation
12
+ - Clear contracts between system components
13
+
14
+ ## Core Principles
15
+
16
+ | Principle | Description |
17
+ |-----------|-------------|
18
+ | **I/O at edges** | Logic blocks are pure functions - no side effects, no hidden state |
19
+ | **Algorithm as text** | Steps described in human-readable prose, not code syntax |
20
+ | **Types explicit** | All data shapes defined with schemas for validation |
21
+ | **State first-class** | State machines declared explicitly, not inferred |
22
+ | **Constraints separate** | Performance/reliability requirements not buried in code |
23
+ | **Failures declared** | Error conditions and recovery strategies part of contract |
24
+ | **Composable blocks** | Logic chains into flows, not monolithic procedures |
25
+ | **Versioned spec** | Schema can evolve without breaking consumers |
26
+ | **Observable** | Hooks for metrics, logging, tracing built-in |
27
+ | **Testable** | Assertions defined alongside logic |
28
+
29
+ ## Specification
30
+
31
+ ### Document Structure
32
+
33
+ ```yaml
34
+ # logic.yaml v1.0
35
+
36
+ meta: # Required - Document metadata
37
+ inputs: # Required - System inputs
38
+ outputs: # Required - System outputs
39
+ types: # Optional - Type definitions
40
+ logic: # Required - Pure logic blocks
41
+ state: # Optional - State machine definition
42
+ flows: # Optional - Logic composition
43
+ failures: # Optional - Error handling
44
+ constraints: # Optional - Performance/reliability bounds
45
+ dependencies: # Optional - External service contracts
46
+ observability: # Optional - Metrics/logging hooks
47
+ tests: # Optional - Built-in assertions
48
+ ```
49
+
50
+ ---
51
+
52
+ ### `meta`
53
+
54
+ Required. Identifies and versions the specification.
55
+
56
+ ```yaml
57
+ meta:
58
+ spec_version: "1.0" # Required - Logic spec version
59
+ name: string # Required - System/module name
60
+ version: string # Required - Semantic version of this logic
61
+ description: string # Optional - Human description
62
+ language_target: string | any # Optional - Target language(s)
63
+ author: string # Optional - Creator
64
+ license: string # Optional - License identifier
65
+ ```
66
+
67
+ **Example:**
68
+ ```yaml
69
+ meta:
70
+ spec_version: "1.0"
71
+ name: user-authenticator
72
+ version: "2.1.0"
73
+ description: Handles user authentication flows
74
+ language_target: any
75
+ ```
76
+
77
+ ---
78
+
79
+ ### `inputs`
80
+
81
+ Required. Defines what enters the system.
82
+
83
+ ```yaml
84
+ inputs:
85
+ - name: string # Required - Input identifier
86
+ type: string # Required - Type name or primitive
87
+ required: boolean # Optional - Default: true
88
+ default: any # Optional - Default value if not required
89
+ description: string # Optional - Purpose of this input
90
+ schema: # Optional - Detailed structure
91
+ field: type
92
+ validation: # Optional - Validation rules
93
+ min: number
94
+ max: number
95
+ pattern: regex
96
+ ```
97
+
98
+ **Primitive types:** `string`, `number`, `boolean`, `array`, `object`, `null`, `any`
99
+
100
+ **Example:**
101
+ ```yaml
102
+ inputs:
103
+ - name: credentials
104
+ type: Credentials
105
+ required: true
106
+ schema:
107
+ username: string
108
+ password: string
109
+ totp_code: string
110
+
111
+ - name: session_duration
112
+ type: number
113
+ required: false
114
+ default: 3600
115
+ validation:
116
+ min: 300
117
+ max: 86400
118
+ ```
119
+
120
+ ---
121
+
122
+ ### `outputs`
123
+
124
+ Required. Defines what leaves the system.
125
+
126
+ ```yaml
127
+ outputs:
128
+ - name: string # Required - Output identifier
129
+ type: string # Required - Type name or primitive
130
+ description: string # Optional - Purpose
131
+ schema: object # Optional - Detailed structure
132
+ ```
133
+
134
+ **Example:**
135
+ ```yaml
136
+ outputs:
137
+ - name: auth_result
138
+ type: AuthResult
139
+ schema:
140
+ success: boolean
141
+ token: string
142
+ expires_at: number
143
+ user_id: string
144
+ ```
145
+
146
+ ---
147
+
148
+ ### `types`
149
+
150
+ Optional. Defines custom types referenced elsewhere.
151
+
152
+ ```yaml
153
+ types:
154
+ TypeName:
155
+ description: string # Optional
156
+ fields: # Required for object types
157
+ field_name: type
158
+ enum: # Required for enum types
159
+ - value1
160
+ - value2
161
+ generic: # Optional - Generic type params
162
+ - T
163
+ ```
164
+
165
+ **Example:**
166
+ ```yaml
167
+ types:
168
+ Credentials:
169
+ fields:
170
+ username: string
171
+ password: string
172
+ totp_code: string | null
173
+
174
+ AuthResult:
175
+ fields:
176
+ success: boolean
177
+ token: string | null
178
+ expires_at: number
179
+ user_id: string | null
180
+ error: AuthError | null
181
+
182
+ AuthError:
183
+ enum:
184
+ - INVALID_CREDENTIALS
185
+ - ACCOUNT_LOCKED
186
+ - TOTP_REQUIRED
187
+ - TOTP_INVALID
188
+ ```
189
+
190
+ ---
191
+
192
+ ### `logic`
193
+
194
+ Required. Pure logic blocks - no I/O, no side effects.
195
+
196
+ ```yaml
197
+ logic:
198
+ - id: string # Required - Unique identifier
199
+ type: string # Required - Block type
200
+ description: string # Optional - What this does
201
+ input: string | array # Required - Input name(s)
202
+ output: string # Required - Output name
203
+ algorithm: string # Required - Steps in prose
204
+ complexity: string # Optional - Big-O notation
205
+ ```
206
+
207
+ **Block types:**
208
+ | Type | Purpose |
209
+ |------|---------|
210
+ | `transform` | Pure data transformation |
211
+ | `validate` | Input validation |
212
+ | `compute` | Calculation/derivation |
213
+ | `decision` | Conditional logic, branching |
214
+ | `aggregate` | Combining multiple inputs |
215
+ | `inference` | AI/ML model invocation |
216
+ | `query` | External data fetch (marked, not pure) |
217
+
218
+ **Example:**
219
+ ```yaml
220
+ logic:
221
+ - id: validate_credentials
222
+ type: validate
223
+ input: credentials
224
+ output: validation_result
225
+ algorithm: |
226
+ 1. Check username format: 3-64 chars, alphanumeric + underscore
227
+ 2. Check password length: >= 12 chars
228
+ 3. If totp_code present, validate 6-digit format
229
+ 4. Return {valid: boolean, errors: string[]}
230
+
231
+ - id: hash_password
232
+ type: transform
233
+ input: credentials.password
234
+ output: hashed_password
235
+ algorithm: |
236
+ 1. Generate salt: 16 random bytes
237
+ 2. Apply Argon2id with salt
238
+ 3. Return base64-encoded hash
239
+ complexity: O(1)
240
+
241
+ - id: verify_password
242
+ type: decision
243
+ input: [credentials, stored_hash]
244
+ output: password_valid
245
+ algorithm: |
246
+ 1. Extract salt from stored_hash
247
+ 2. Hash input password with same salt
248
+ 3. Compare with constant-time comparison
249
+ 4. Return boolean
250
+ ```
251
+
252
+ ---
253
+
254
+ ### `state`
255
+
256
+ Optional. State machine definition.
257
+
258
+ ```yaml
259
+ state:
260
+ initial: string # Required - Starting state
261
+ persist: boolean # Optional - Persist across runs
262
+ states: # Optional - State definitions
263
+ state_name:
264
+ description: string
265
+ transitions: # Required - State transitions
266
+ - from: string | array
267
+ to: string
268
+ trigger: string # Event or condition
269
+ action: string # Optional - Logic block to execute
270
+ guard: string # Optional - Condition that must be true
271
+ ```
272
+
273
+ **Example:**
274
+ ```yaml
275
+ state:
276
+ initial: unauthenticated
277
+ persist: true
278
+ states:
279
+ unauthenticated:
280
+ description: No active session
281
+ authenticating:
282
+ description: Login in progress
283
+ authenticated:
284
+ description: Valid session active
285
+ locked:
286
+ description: Account locked due to failures
287
+
288
+ transitions:
289
+ - from: unauthenticated
290
+ to: authenticating
291
+ trigger: login_attempt
292
+ action: validate_credentials
293
+
294
+ - from: authenticating
295
+ to: authenticated
296
+ trigger: credentials_valid
297
+ action: create_session
298
+ guard: attempts < 5
299
+
300
+ - from: authenticating
301
+ to: locked
302
+ trigger: too_many_failures
303
+ guard: attempts >= 5
304
+
305
+ - from: authenticated
306
+ to: unauthenticated
307
+ trigger: logout | session_expired
308
+ action: destroy_session
309
+ ```
310
+
311
+ ---
312
+
313
+ ### `flows`
314
+
315
+ Optional. Composition of logic blocks into sequences.
316
+
317
+ ```yaml
318
+ flows:
319
+ - name: string # Required - Flow identifier
320
+ description: string # Optional
321
+ steps: array # Required - Logic block IDs in order
322
+ parallel: boolean # Optional - Run steps in parallel
323
+ timeout_ms: number # Optional - Max execution time
324
+ retry: # Optional - Retry configuration
325
+ count: number
326
+ backoff: linear | exponential
327
+ delay_ms: number
328
+ ```
329
+
330
+ **Example:**
331
+ ```yaml
332
+ flows:
333
+ - name: authenticate_user
334
+ description: Full authentication flow
335
+ steps:
336
+ - validate_credentials
337
+ - verify_password
338
+ - check_account_status
339
+ - create_session
340
+ parallel: false
341
+ timeout_ms: 5000
342
+
343
+ - name: parallel_validation
344
+ steps:
345
+ - validate_credentials
346
+ - check_rate_limit
347
+ - check_ip_reputation
348
+ parallel: true
349
+ timeout_ms: 1000
350
+ ```
351
+
352
+ ---
353
+
354
+ ### `failures`
355
+
356
+ Optional. Error conditions and recovery strategies.
357
+
358
+ ```yaml
359
+ failures:
360
+ - code: string # Required - Error code
361
+ condition: string # Required - When this occurs
362
+ severity: critical | error | warning | info
363
+ recovery: # Optional - Recovery strategy
364
+ strategy: retry | fallback | escalate | ignore
365
+ retry_count: number # For retry strategy
366
+ fallback_to: string # For fallback strategy
367
+ message: string # Optional - Human-readable message
368
+ ```
369
+
370
+ **Example:**
371
+ ```yaml
372
+ failures:
373
+ - code: E001
374
+ condition: "database.connection_timeout > 5000ms"
375
+ severity: error
376
+ recovery:
377
+ strategy: retry
378
+ retry_count: 3
379
+ message: Database connection timed out
380
+
381
+ - code: E002
382
+ condition: "password_hash.failure"
383
+ severity: critical
384
+ recovery:
385
+ strategy: escalate
386
+ message: Password hashing failed - possible security issue
387
+
388
+ - code: E003
389
+ condition: "rate_limit.exceeded"
390
+ severity: warning
391
+ recovery:
392
+ strategy: fallback
393
+ fallback_to: cached_response
394
+ message: Rate limit exceeded
395
+ ```
396
+
397
+ ---
398
+
399
+ ### `constraints`
400
+
401
+ Optional. Performance and reliability bounds.
402
+
403
+ ```yaml
404
+ constraints:
405
+ latency_max_ms: number # Max response time
406
+ throughput_min_rps: number # Min requests per second
407
+ memory_limit_mb: number # Max memory usage
408
+ cpu_limit_percent: number # Max CPU usage
409
+ availability_percent: number # Uptime requirement
410
+ data_retention_days: number # Data storage duration
411
+ ```
412
+
413
+ **Example:**
414
+ ```yaml
415
+ constraints:
416
+ latency_max_ms: 500
417
+ throughput_min_rps: 1000
418
+ memory_limit_mb: 512
419
+ availability_percent: 99.9
420
+ ```
421
+
422
+ ---
423
+
424
+ ### `dependencies`
425
+
426
+ Optional. External service contracts.
427
+
428
+ ```yaml
429
+ dependencies:
430
+ - name: string # Required - Service name
431
+ type: string # Required - Service type
432
+ contract: string # Optional - Interface name
433
+ required: boolean # Optional - Default: true
434
+ endpoint: string # Optional - Service URL
435
+ timeout_ms: number # Optional - Request timeout
436
+ auth: string # Optional - Auth method
437
+ ```
438
+
439
+ **Example:**
440
+ ```yaml
441
+ dependencies:
442
+ - name: user_database
443
+ type: database
444
+ contract: UserStore
445
+ required: true
446
+ timeout_ms: 1000
447
+
448
+ - name: cache
449
+ type: cache
450
+ contract: KeyValueStore
451
+ required: false
452
+
453
+ - name: gemini_api
454
+ type: external_service
455
+ contract: VisionAPI
456
+ required: true
457
+ timeout_ms: 30000
458
+ auth: api_key
459
+ ```
460
+
461
+ ---
462
+
463
+ ### `observability`
464
+
465
+ Optional. Metrics, logging, and tracing hooks.
466
+
467
+ ```yaml
468
+ observability:
469
+ metrics:
470
+ - name: string # Required - Metric name
471
+ type: counter | gauge | histogram
472
+ unit: string # Optional - Unit of measurement
473
+ labels: array # Optional - Dimension labels
474
+
475
+ logs:
476
+ level: debug | info | warn | error
477
+ include: array # Fields to include in logs
478
+ exclude: array # Fields to redact
479
+
480
+ traces:
481
+ enabled: boolean
482
+ sample_rate: number # 0.0 to 1.0
483
+ ```
484
+
485
+ **Example:**
486
+ ```yaml
487
+ observability:
488
+ metrics:
489
+ - name: auth_attempts_total
490
+ type: counter
491
+ labels: [status, method]
492
+ - name: auth_duration_ms
493
+ type: histogram
494
+ unit: ms
495
+
496
+ logs:
497
+ level: info
498
+ include: [user_id, method, duration_ms]
499
+ exclude: [password, token]
500
+
501
+ traces:
502
+ enabled: true
503
+ sample_rate: 0.1
504
+ ```
505
+
506
+ ---
507
+
508
+ ### `tests`
509
+
510
+ Optional. Built-in assertions and test cases.
511
+
512
+ ```yaml
513
+ tests:
514
+ - name: string # Required - Test name
515
+ description: string # Optional
516
+ given: object # Required - Input values
517
+ when: string # Optional - Action/flow to execute
518
+ expect: object # Required - Expected outputs
519
+ timeout_ms: number # Optional
520
+ ```
521
+
522
+ **Matchers in `expect`:**
523
+ | Syntax | Meaning |
524
+ |--------|---------|
525
+ | `value` | Exact match |
526
+ | `">= n"` | Greater than or equal |
527
+ | `"<= n"` | Less than or equal |
528
+ | `"type:typename"` | Type check |
529
+ | `"/regex/"` | Regex match |
530
+ | `"!null"` | Not null |
531
+ | `"any"` | Any value (just check presence) |
532
+
533
+ **Example:**
534
+ ```yaml
535
+ tests:
536
+ - name: valid_login
537
+ description: Successful authentication with valid credentials
538
+ given:
539
+ credentials:
540
+ username: testuser
541
+ password: correct_password_123
542
+ when: authenticate_user
543
+ expect:
544
+ auth_result.success: true
545
+ auth_result.token: "!null"
546
+ auth_result.expires_at: ">= 0"
547
+
548
+ - name: invalid_password
549
+ given:
550
+ credentials:
551
+ username: testuser
552
+ password: wrong_password
553
+ when: authenticate_user
554
+ expect:
555
+ auth_result.success: false
556
+ auth_result.error: INVALID_CREDENTIALS
557
+
558
+ - name: rate_limited
559
+ given:
560
+ credentials:
561
+ username: testuser
562
+ password: any_password
563
+ rate_limit_exceeded: true
564
+ expect:
565
+ auth_result.success: false
566
+ auth_result.error: RATE_LIMITED
567
+ ```
568
+
569
+ ---
570
+
571
+ ## Complete Example
572
+
573
+ ```yaml
574
+ # logic.yaml - User Authentication Module
575
+
576
+ meta:
577
+ spec_version: "1.0"
578
+ name: user-auth
579
+ version: "1.0.0"
580
+ description: User authentication with password and TOTP
581
+ language_target: any
582
+
583
+ inputs:
584
+ - name: credentials
585
+ type: Credentials
586
+ required: true
587
+ - name: client_ip
588
+ type: string
589
+ required: true
590
+ - name: session_duration
591
+ type: number
592
+ default: 3600
593
+
594
+ outputs:
595
+ - name: auth_result
596
+ type: AuthResult
597
+
598
+ types:
599
+ Credentials:
600
+ fields:
601
+ username: string
602
+ password: string
603
+ totp_code: string | null
604
+
605
+ AuthResult:
606
+ fields:
607
+ success: boolean
608
+ token: string | null
609
+ expires_at: number
610
+ user_id: string | null
611
+ error: AuthError | null
612
+
613
+ AuthError:
614
+ enum: [INVALID_CREDENTIALS, ACCOUNT_LOCKED, TOTP_REQUIRED, TOTP_INVALID, RATE_LIMITED]
615
+
616
+ logic:
617
+ - id: validate_input
618
+ type: validate
619
+ input: credentials
620
+ output: validation
621
+ algorithm: |
622
+ 1. Validate username format
623
+ 2. Validate password length >= 12
624
+ 3. Return {valid: boolean, errors: string[]}
625
+
626
+ - id: check_rate_limit
627
+ type: decision
628
+ input: client_ip
629
+ output: rate_ok
630
+ algorithm: |
631
+ 1. Count recent attempts from IP
632
+ 2. Return true if under limit, false otherwise
633
+
634
+ - id: verify_credentials
635
+ type: decision
636
+ input: [credentials, stored_user]
637
+ output: credentials_valid
638
+ algorithm: |
639
+ 1. Fetch stored hash for username
640
+ 2. Compare passwords with constant-time comparison
641
+ 3. If TOTP enabled, verify code
642
+ 4. Return boolean
643
+
644
+ - id: create_session
645
+ type: transform
646
+ input: [user_id, session_duration]
647
+ output: auth_result
648
+ algorithm: |
649
+ 1. Generate secure random token
650
+ 2. Set expiration = now + session_duration
651
+ 3. Store session in cache
652
+ 4. Return AuthResult with success=true
653
+
654
+ state:
655
+ initial: idle
656
+ transitions:
657
+ - from: idle
658
+ to: validating
659
+ trigger: login_attempt
660
+ - from: validating
661
+ to: authenticating
662
+ trigger: input_valid
663
+ - from: validating
664
+ to: idle
665
+ trigger: input_invalid
666
+ - from: authenticating
667
+ to: success
668
+ trigger: credentials_valid
669
+ - from: authenticating
670
+ to: failed
671
+ trigger: credentials_invalid
672
+ - from: success
673
+ to: idle
674
+ trigger: logout
675
+
676
+ flows:
677
+ - name: authenticate
678
+ steps: [validate_input, check_rate_limit, verify_credentials, create_session]
679
+ timeout_ms: 5000
680
+
681
+ failures:
682
+ - code: E001
683
+ condition: "rate_limit.exceeded"
684
+ recovery:
685
+ strategy: fallback
686
+ fallback_to: rate_limit_response
687
+ - code: E002
688
+ condition: "database.unavailable"
689
+ recovery:
690
+ strategy: retry
691
+ retry_count: 3
692
+
693
+ constraints:
694
+ latency_max_ms: 500
695
+ throughput_min_rps: 1000
696
+ availability_percent: 99.9
697
+
698
+ dependencies:
699
+ - name: user_db
700
+ type: database
701
+ contract: UserStore
702
+ - name: session_cache
703
+ type: cache
704
+ contract: KeyValueStore
705
+ - name: rate_limiter
706
+ type: service
707
+ contract: RateLimiter
708
+
709
+ observability:
710
+ metrics:
711
+ - name: auth_attempts
712
+ type: counter
713
+ labels: [status, method]
714
+ - name: auth_latency
715
+ type: histogram
716
+ unit: ms
717
+ logs:
718
+ level: info
719
+ include: [user_id, client_ip, duration_ms]
720
+ exclude: [password, token]
721
+
722
+ tests:
723
+ - name: happy_path
724
+ given:
725
+ credentials: {username: alice, password: secure_password_123}
726
+ client_ip: 192.168.1.1
727
+ expect:
728
+ auth_result.success: true
729
+ auth_result.token: "!null"
730
+
731
+ - name: wrong_password
732
+ given:
733
+ credentials: {username: alice, password: wrong_password}
734
+ client_ip: 192.168.1.1
735
+ expect:
736
+ auth_result.success: false
737
+ auth_result.error: INVALID_CREDENTIALS
738
+ ```
739
+
740
+ ---
741
+
742
+ ## Validation Rules
743
+
744
+ A valid `logic.yaml` must pass these checks:
745
+
746
+ 1. **Required fields present**: `meta`, `inputs`, `outputs`, `logic`
747
+ 2. **Unique identifiers**: All `logic[].id`, `types` keys, `inputs[].name`, `outputs[].name` must be unique
748
+ 3. **Type references**: All referenced types must be defined in `types` or be primitives
749
+ 4. **Input/output connectivity**: Each `logic[].input` must reference a defined input or another logic block's output
750
+ 5. **State transitions**: All states in `transitions` must be defined
751
+ 6. **Test coverage**: Each `flow` should have at least one test case
752
+
753
+ ---
754
+
755
+ ## Versioning
756
+
757
+ The spec uses semantic versioning:
758
+
759
+ - **Major**: Breaking changes to required structure
760
+ - **Minor**: New optional fields added
761
+ - **Patch**: Clarifications, no structural changes
762
+
763
+ Current version: **1.0.0**
764
+
765
+ ---
766
+
767
+ ## Tooling
768
+
769
+ Recommended tooling for `logic.yaml`:
770
+
771
+ | Tool | Purpose |
772
+ |------|---------|
773
+ | `logic-validate` | Validate spec against schema |
774
+ | `logic-generate` | Generate code from spec |
775
+ | `logic-docs` | Generate documentation |
776
+ | `logic-test` | Run built-in test cases |
777
+ | `logic-visualize` | Generate state/flow diagrams |
778
+
779
+ ---
780
+
781
+ ## License
782
+
783
+ This specification is released under the MIT License.