thefinalboss commited on
Commit
f3553d6
·
verified ·
1 Parent(s): 6b2ebea

Add AICL example: 18_mvc_webapp.aicl

Browse files
Files changed (1) hide show
  1. data/aicl/examples/18_mvc_webapp.aicl +408 -0
data/aicl/examples/18_mvc_webapp.aicl ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AICL Example: MVC Web Application
2
+ # Implements a full Model-View-Controller web application with routing, middleware pipeline,
3
+ # session management, template rendering, input validation, and CSRF protection.
4
+
5
+ # Level 1: Architecture
6
+ Goal: Build a production MVC web application framework supporting clean separation of concerns,
7
+ declarative routing with parameter extraction, middleware pipeline for cross-cutting logic,
8
+ secure session management, and view template rendering with layout inheritance.
9
+
10
+ Constraint: Controllers must not contain business logic; delegate to service layer.
11
+ Constraint: Views must not execute arbitrary code; only template expressions permitted.
12
+ Constraint: All user input must be validated before reaching controller logic.
13
+ Constraint: Session data must be stored server-side; client holds only a signed session ID.
14
+ Constraint: Each route must declare its HTTP method, path pattern, and required middleware.
15
+
16
+ Risk: Session hijacking via stolen session cookie
17
+ Recovery: Regenerate session ID on privilege elevation; bind session to IP and user-agent fingerprint
18
+
19
+ Risk: CSRF token bypass on state-changing requests
20
+ Recovery: Double-submit cookie pattern with SameSite=Strict attribute and token rotation per request
21
+
22
+ Risk: Template injection through unsanitized user input
23
+ Recovery: Auto-escape all template expressions by default; explicit unescape requires safe annotation
24
+
25
+ Risk: Route collision causing request misrouting
26
+ Recovery: Detect route conflicts at startup; first-registered wins with warning for duplicates
27
+
28
+ Risk: Middleware ordering causes authentication bypass
29
+ Recovery: Enforce middleware dependency graph; validate ordering at route registration time
30
+
31
+ Risk: Memory leak from unbounded session store
32
+ Recovery: Set session TTL of 30 minutes; background sweeper evicts expired sessions every 60 seconds
33
+
34
+ Layer: Presentation
35
+ SubLayer: Router
36
+ SubLayer: Controller
37
+ SubLayer: ViewRenderer
38
+ SubLayer: Middleware
39
+ Layer: Application
40
+ SubLayer: SessionManager
41
+ SubLayer: AuthService
42
+ SubLayer: ValidationService
43
+ SubLayer: FlashMessenger
44
+ Layer: Data
45
+ SubLayer: Model
46
+ SubLayer: Repository
47
+ SubLayer: DatabasePool
48
+
49
+ Validation: Route path parameters must match declared regex patterns
50
+ Validation: Request body must conform to content-type schema before controller dispatch
51
+ Validation: Session ID must be cryptographically signed and unexpired
52
+ Validation: CSRF token must match server-side stored token for the session
53
+ Validation: Response content-type must match route declaration
54
+ Validation: Middleware pipeline must not skip authentication for protected routes
55
+
56
+ # Level 2: Entities
57
+ Entity Route
58
+ routeId: string
59
+ httpMethod: string
60
+ pathPattern: string
61
+ controllerName: string
62
+ actionName: string
63
+ middlewareStack: list
64
+ requiredRoles: list
65
+ parameterConstraints: dict
66
+ cacheTtl: integer
67
+
68
+ Entity Controller
69
+ controllerName: string
70
+ actions: dict
71
+ beforeFilters: list
72
+ afterFilters: list
73
+ layout: string
74
+ rescues: dict
75
+ namespace: string
76
+
77
+ Entity ViewTemplate
78
+ templateId: string
79
+ templateName: string
80
+ layout: string
81
+ partials: list
82
+ helpers: list
83
+ lastModified: datetime
84
+ compiledAt: datetime
85
+ cacheEnabled: boolean
86
+ mimeType: string
87
+
88
+ Entity Session
89
+ sessionId: string
90
+ userId: string
91
+ data: dict
92
+ createdAt: datetime
93
+ lastAccessedAt: datetime
94
+ expiresAt: datetime
95
+ ipAddress: string
96
+ userAgent: string
97
+ csrfToken: string
98
+
99
+ Entity HttpRequest
100
+ requestId: string
101
+ method: string
102
+ path: string
103
+ headers: dict
104
+ queryParams: dict
105
+ bodyParams: dict
106
+ routeParams: dict
107
+ session: Session
108
+ contentType: string
109
+ ipAddress: string
110
+
111
+ Entity Middleware
112
+ middlewareId: string
113
+ middlewareName: string
114
+ priority: integer
115
+ dependencies: list
116
+ config: dict
117
+ enabled: boolean
118
+ scope: string
119
+
120
+ # Level 3: Behaviors
121
+ Behavior MatchRoute
122
+ Input:
123
+ method: string
124
+ path: string
125
+ Output:
126
+ route: Route
127
+ params: dict
128
+ Action:
129
+ Scan route table for matching HTTP method
130
+ Apply path pattern matching with parameter extraction
131
+ Resolve route parameters against declared constraints
132
+ Verify required middleware is available
133
+ Return matched route with extracted parameters
134
+
135
+ Behavior DispatchRequest
136
+ Input:
137
+ request: HttpRequest
138
+ route: Route
139
+ Output:
140
+ response: dict
141
+ Action:
142
+ Execute middleware pipeline in priority order
143
+ Instantiate controller with request context
144
+ Apply before-filters on controller
145
+ Invoke controller action with route parameters
146
+ Apply after-filters on controller
147
+ Execute post-action middleware in reverse order
148
+ Return rendered response
149
+
150
+ Behavior RenderView
151
+ Input:
152
+ templateName: string
153
+ locals: dict
154
+ layout: string
155
+ Output:
156
+ renderedHtml: string
157
+ Action:
158
+ Resolve template file from template registry
159
+ Compile template if not cached or modified since compilation
160
+ Render partials and helpers into template context
161
+ Apply auto-escaping to all interpolated values
162
+ Render layout with yielded content
163
+ Cache rendered output if cacheEnabled
164
+ Return rendered HTML string
165
+
166
+ Behavior ManageSession
167
+ Input:
168
+ sessionId: string
169
+ operation: string
170
+ data: dict
171
+ Output:
172
+ session: Session
173
+ Action:
174
+ Validate session ID signature and expiration
175
+ Load session data from server-side store
176
+ Apply operation: create, read, update, destroy
177
+ Regenerate ID if privilege elevation detected
178
+ Update last accessed timestamp
179
+ Persist session changes to store
180
+
181
+ Behavior ValidateInput
182
+ Input:
183
+ params: dict
184
+ rules: dict
185
+ Output:
186
+ sanitized: dict
187
+ errors: list
188
+ Action:
189
+ Check each parameter against its validation rule
190
+ Apply type coercion where appropriate
191
+ Sanitize strings against XSS patterns
192
+ Collect all validation errors without short-circuiting
193
+ Return sanitized params and error list
194
+
195
+ Behavior AuthenticateRequest
196
+ Input:
197
+ request: HttpRequest
198
+ requiredRoles: list
199
+ Output:
200
+ authenticated: boolean
201
+ userId: string
202
+ Action:
203
+ Extract session cookie from request headers
204
+ Validate session ID and load session data
205
+ Check user roles against required roles
206
+ Verify IP and user-agent match session fingerprint
207
+ Return authentication result
208
+
209
+ # Level 4: Conditions
210
+ Condition: SessionExpired
211
+ When session lastAccessedAt exceeds configured TTL
212
+ Then destroy session, clear cookie, and redirect to login with flash message
213
+
214
+ Condition: UnauthorizedAccess
215
+ When authenticated user lacks required role for route
216
+ Then return HTTP 403 with insufficient-privileges view and log attempt
217
+
218
+ Condition: ValidationFailure
219
+ When input validation produces any errors
220
+ Then re-render form view with error messages and preserved input values
221
+
222
+ # Level 5: Events
223
+ Event: OnRequestReceived
224
+ On new HTTP request entering the middleware pipeline
225
+ Action: Start request timer, inject correlation ID, and attach trace context
226
+
227
+ Event: OnAuthenticationFailure
228
+ On session validation or role check failure
229
+ Action: Log security event with IP and user-agent, increment failed auth metric
230
+
231
+ Event: OnSessionCreated
232
+ On new session established after successful login
233
+ Action: Emit audit event, set session cookie with Secure and HttpOnly flags
234
+
235
+ Event: OnRouteNotFound
236
+ On no matching route found for request path and method
237
+ Action: Return HTTP 404 with custom not-found view and log path for analysis
238
+
239
+ # Level 6: Concurrency
240
+ Parallel:
241
+ Request handling across multiple worker processes
242
+ Session store read/write operations with optimistic locking
243
+ Template compilation for modified views in background
244
+ Middleware execution for independent concerns (logging, metrics, CORS)
245
+ Static asset serving on separate thread pool from dynamic requests
246
+
247
+ # Level 7: Optimization
248
+ Optimize: Request processing latency
249
+ Priority: Cache compiled templates; pool database connections; minimize middleware overhead per route
250
+
251
+ Optimize: View rendering throughput
252
+ Priority: Pre-compile templates at startup; cache rendered fragments with key-based expiration
253
+
254
+ # Level 8: Learning
255
+ Learn: Route popularity patterns
256
+ Goal: Identify high-traffic routes for pre-warming and connection pool sizing
257
+ Adapt: Per-route connection pool allocation
258
+ Based: Request frequency distribution and latency percentiles over sliding 15-minute window
259
+
260
+ Learn: Session store sizing
261
+ Goal: Predict session store memory requirements based on traffic patterns
262
+ Adapt: Session TTL and eviction aggressiveness
263
+ Based: Concurrent session count trends and average session data size
264
+
265
+ # Level 9: Security
266
+ Security:
267
+ Encrypt: Session cookie using HMAC-SHA256 with rotating secret key
268
+ Encrypt: Sensitive session data fields with AES-256-GCM server-side encryption
269
+ Protect: All forms against CSRF with per-request token validation and SameSite cookies
270
+ Protect: Application against XSS with Content-Security-Policy headers and auto-escaping
271
+ Protect: Upload endpoints against file inclusion with mime-type validation and sandboxed storage
272
+
273
+ # Level 10: Native
274
+ Go
275
+ {
276
+ package mvc
277
+
278
+ import (
279
+ "crypto/hmac"
280
+ "crypto/sha256"
281
+ "encoding/hex"
282
+ "fmt"
283
+ "net/http"
284
+ "regexp"
285
+ "sync"
286
+ "time"
287
+ )
288
+
289
+ type Route struct {
290
+ Method string
291
+ Pattern *regexp.Regexp
292
+ Handler http.HandlerFunc
293
+ Middleware []func(http.Handler) http.Handler
294
+ Params []string
295
+ }
296
+
297
+ type Router struct {
298
+ routes []Route
299
+ mu sync.RWMutex
300
+ }
301
+
302
+ func NewRouter() *Router {
303
+ return &Router{}
304
+ }
305
+
306
+ func (r *Router) AddRoute(method, pattern string, handler http.HandlerFunc, middleware ...func(http.Handler) http.Handler) {
307
+ re := regexp.MustCompile(pattern)
308
+ paramRe := regexp.MustCompile(`:([a-zA-Z]+)`)
309
+ matches := paramRe.FindAllStringSubmatch(pattern, -1)
310
+ params := make([]string, 0)
311
+ for _, m := range matches {
312
+ params = append(params, m[1])
313
+ }
314
+ r.mu.Lock()
315
+ r.routes = append(r.routes, Route{
316
+ Method: method, Pattern: re, Handler: handler,
317
+ Middleware: middleware, Params: params,
318
+ })
319
+ r.mu.Unlock()
320
+ }
321
+
322
+ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
323
+ r.mu.RLock()
324
+ defer r.mu.RUnlock()
325
+ for _, route := range r.routes {
326
+ if route.Method != req.Method {
327
+ continue
328
+ }
329
+ matches := route.Pattern.FindStringSubmatch(req.URL.Path)
330
+ if matches == nil {
331
+ continue
332
+ }
333
+ for i, name := range route.Params {
334
+ if i+1 < len(matches) {
335
+ req.URL.RawQuery += fmt.Sprintf("&%s=%s", name, matches[i+1])
336
+ }
337
+ }
338
+ var handler http.Handler = route.Handler
339
+ for i := len(route.Middleware) - 1; i >= 0; i-- {
340
+ handler = route.Middleware[i](handler)
341
+ }
342
+ handler.ServeHTTP(w, req)
343
+ return
344
+ }
345
+ http.NotFound(w, req)
346
+ }
347
+
348
+ type SessionManager struct {
349
+ store map[string]*Session
350
+ secret []byte
351
+ mu sync.RWMutex
352
+ }
353
+
354
+ type Session struct {
355
+ ID string
356
+ Data map[string]interface{}
357
+ CreatedAt time.Time
358
+ ExpiresAt time.Time
359
+ CSRFToken string
360
+ }
361
+
362
+ func NewSessionManager(secret string) *SessionManager {
363
+ sm := &SessionManager{
364
+ store: make(map[string]*Session),
365
+ secret: []byte(secret),
366
+ }
367
+ go sm.sweepExpired()
368
+ return sm
369
+ }
370
+
371
+ func (sm *SessionManager) Create(w http.ResponseWriter) *Session {
372
+ id := generateToken(sm.secret)
373
+ session := &Session{
374
+ ID: id, Data: make(map[string]interface{}),
375
+ CreatedAt: time.Now(), ExpiresAt: time.Now().Add(30 * time.Minute),
376
+ CSRFToken: generateToken(sm.secret),
377
+ }
378
+ sm.mu.Lock()
379
+ sm.store[id] = session
380
+ sm.mu.Unlock()
381
+ http.SetCookie(w, &http.Cookie{
382
+ Name: "session_id", Value: id,
383
+ HttpOnly: true, Secure: true, SameSite: http.SameSiteStrictMode,
384
+ Path: "/", MaxAge: 1800,
385
+ })
386
+ return session
387
+ }
388
+
389
+ func (sm *SessionManager) sweepExpired() {
390
+ ticker := time.NewTicker(60 * time.Second)
391
+ for range ticker.C {
392
+ sm.mu.Lock()
393
+ now := time.Now()
394
+ for id, s := range sm.store {
395
+ if now.After(s.ExpiresAt) {
396
+ delete(sm.store, id)
397
+ }
398
+ }
399
+ sm.mu.Unlock()
400
+ }
401
+ }
402
+
403
+ func generateToken(secret []byte) string {
404
+ h := hmac.New(sha256.New, secret)
405
+ h.Write([]byte(fmt.Sprintf("%d", time.Now().UnixNano())))
406
+ return hex.EncodeToString(h.Sum(nil))
407
+ }
408
+ }