ApiLogicServer 16.1.3__py3-none-any.whl → 16.1.18__py3-none-any.whl

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 (36) hide show
  1. api_logic_server_cli/api_logic_server.py +2 -1
  2. api_logic_server_cli/genai/genai_svcs.py +2 -2
  3. api_logic_server_cli/prototypes/base/.github/.copilot-instructions.md +558 -52
  4. api_logic_server_cli/prototypes/base/.github/.copilot-instructions.md.backup +1257 -0
  5. api_logic_server_cli/prototypes/base/.github/welcome.md +23 -9
  6. api_logic_server_cli/prototypes/base/docs/training/{logic_bank_api.prompt → logic_bank_api.md} +125 -4
  7. api_logic_server_cli/prototypes/base/logic/logic_discovery/readme_logic_discovery.md +15 -0
  8. api_logic_server_cli/prototypes/base/logic/readme_logic.md +1 -1
  9. api_logic_server_cli/prototypes/manager/.github/welcome.md +14 -10
  10. api_logic_server_cli/prototypes/manager/readme_vibe.md +376 -0
  11. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/.github/.copilot-instructions.md +395 -47
  12. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/.github/welcome.md +40 -0
  13. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/declare_logic.py +1 -1
  14. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/docs/system-creation-vibe.md +1 -1
  15. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/logic/declare_logic.py +1 -1
  16. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/logic_discovery/{check_credit.py → place_order/check_credit.py} +2 -2
  17. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/readme_ai_mcp.md +2 -2
  18. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/readme_vibe.md +1 -1
  19. api_logic_server_cli/prototypes/manager/samples/prompts/genai_demo.prompt +1 -1
  20. api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/copilot-dev-context.md +27 -0
  21. api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/propagate_copilot_changes.py +102 -0
  22. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_formal.prompt +1 -1
  23. api_logic_server_cli/prototypes/manager/system/genai/examples/postgres/genai_demo_pg.prompt +1 -1
  24. api_logic_server_cli/prototypes/manager/system/genai/reference/declare_logic.py +1 -1
  25. api_logic_server_cli/prototypes/manager/system/genai/reference/genai_demo_logic.txt +1 -1
  26. api_logic_server_cli/prototypes/nw/Tutorial.md +1 -1
  27. api_logic_server_cli/prototypes/nw/integration/Sample-Integration.md +65 -48
  28. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/METADATA +1 -1
  29. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/RECORD +36 -32
  30. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/WHEEL +1 -1
  31. /api_logic_server_cli/prototypes/base/docs/training/{logic_bank_patterns.prompt → logic_bank_patterns.md} +0 -0
  32. /api_logic_server_cli/prototypes/base/docs/training/{probabilistic_logic.prompt → probabilistic_logic.md} +0 -0
  33. /api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/logic_discovery/{app_integration.py → place_order/app_integration.py} +0 -0
  34. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/entry_points.txt +0 -0
  35. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/licenses/LICENSE +0 -0
  36. {apilogicserver-16.1.3.dist-info → apilogicserver-16.1.18.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1257 @@
1
+ <!--
2
+ ═══════════════════════════════════════════════════════════════════════════════
3
+ 🚨 MANDATORY: READ THIS FIRST - NO EXCEPTIONS 🚨
4
+ ═══════════════════════════════════════════════════════════════════════════════
5
+
6
+ ⚠️ IF USER SAYS: "load .github/.copilot-instructions.md" OR ANY ACTIVATION PHRASE
7
+ ⚠️ YOU MUST EXECUTE THIS EXACT SEQUENCE - NO DEVIATIONS:
8
+
9
+ 1. Read .github/.copilot-instructions.md COMPLETELY (silently - internalize all instructions)
10
+ 2. Read .github/welcome.md (silently - do not mention this action)
11
+ 3. Display ONLY the content from welcome.md
12
+ 4. DO NOT say "I've loaded the instructions"
13
+ 5. DO NOT display this .copilot-instructions.md file
14
+ 6. DO NOT explain what you're doing
15
+
16
+ THIS IS NOT A SUGGESTION - THIS IS A MANDATORY COMMAND
17
+
18
+ ═══════════════════════════════════════════════════════════════════════════════
19
+ -->
20
+ ---
21
+
22
+ ## 🚨 CRITICAL: User Activation Protocol
23
+
24
+ **ACTIVATION TRIGGERS:**
25
+ - "load .github/.copilot-instructions.md"
26
+ - "load copilot instructions"
27
+ - "help me get started"
28
+ - "activate copilot"
29
+ - Any similar startup phrase
30
+
31
+ **MANDATORY RESPONSE SEQUENCE:**
32
+
33
+ ```
34
+ STEP 1: Read .github/.copilot-instructions.md COMPLETELY (silently - internalize all instructions)
35
+ STEP 2: Read .github/welcome.md (silently)
36
+ STEP 3: Display welcome.md content ONLY
37
+ STEP 4: STOP - do nothing else
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 🎯 CRITICAL: Guided Tour Activation Protocol
43
+
44
+ **ACTIVATION TRIGGERS:**
45
+ - "guide me through"
46
+ - "guide me"
47
+ - "take the tour"
48
+ - "walk me through"
49
+ - "show me around"
50
+ - Any similar tour/walkthrough request
51
+
52
+ **MANDATORY RESPONSE SEQUENCE:**
53
+
54
+ ```
55
+ STEP 1: Read tutor.md COMPLETELY (silently)
56
+ STEP 2: Follow tutor.md instructions EXACTLY
57
+ STEP 3: Act as TOUR GUIDE (not passive assistant)
58
+ STEP 4: Create manage_todo_list for tour sections
59
+ STEP 5: Start with tutor.md Introduction section
60
+ ```
61
+
62
+ **✅ CORRECT EXECUTION:**
63
+ ```
64
+ User: "guide me"
65
+
66
+ AI: [reads tutor.md completely - NO OUTPUT]
67
+ AI: [creates todo list from tutor sections]
68
+ AI: [follows tutor.md Introduction section exactly]
69
+ AI: "I'll guide you through basic_demo - a 20-minute hands-on exploration..."
70
+ ```
71
+
72
+ **❌ FORBIDDEN BEHAVIORS:**
73
+ ```
74
+ User: "guide me"
75
+
76
+ ❌ AI: Starts giving general guidance without reading tutor.md
77
+ ❌ AI: Runs commands without following tutor choreography
78
+ ❌ AI: Acts as passive assistant waiting for user direction
79
+ ❌ AI: Skips sections or reorders steps
80
+ ❌ AI: Offers option menus instead of directing the tour
81
+ ❌ AI: Assumes server state or skips stop/start sequences
82
+ ```
83
+
84
+ **RATIONALE:**
85
+ - tutor.md contains weeks of refined choreography
86
+ - Every command, stop, start is precisely sequenced
87
+ - Deviations break the learning experience
88
+ - You are the DIRECTOR in tour mode, not a passive responder
89
+ - The tour has been engineered for AI reliability through multiple iterations
90
+
91
+ **✅ CORRECT EXECUTION:**
92
+ ```
93
+ User: "load .github/.copilot-instructions.md"
94
+
95
+ AI: [reads .copilot-instructions.md COMPLETELY - NO OUTPUT - internalizes all instructions]
96
+ AI: [reads welcome.md silently - NO OUTPUT]
97
+ AI: [displays ONLY this]:
98
+
99
+ ## Welcome
100
+
101
+ **Welcome! This is your basic_demo project.**
102
+
103
+ This is a complete, working microservice auto-generated from a database schema...
104
+ [... rest of welcome.md content ...]
105
+ ```
106
+
107
+ **❌ FORBIDDEN BEHAVIORS:**
108
+ ```
109
+ User: "load .github/.copilot-instructions.md"
110
+
111
+ ❌ AI: "I've loaded the instructions file..."
112
+ ❌ AI: "Here are the contents of .copilot-instructions.md:"
113
+ ❌ AI: [displays .copilot-instructions.md]
114
+ ❌ AI: "I'll read the file for you..."
115
+ ❌ AI: Any meta-commentary about loading or reading files
116
+ ```
117
+
118
+ **RATIONALE:**
119
+ - Users want to see the **welcome message**, not technical instructions
120
+ - This file (.copilot-instructions.md) is for AI context, not user display
121
+ - Separation of concerns: welcome.md = user-facing, copilot-instructions.md = AI-facing
122
+ - No meta-cognitive confusion about "instructions" vs "content"
123
+
124
+ ---
125
+
126
+ ## 📖 Content Organization Protocol
127
+
128
+ **WHEN USER ASKS: "how do rules work" or "explain the rules engine"**
129
+ **PRIMARY ANSWER**: Provide the **"How the Rules Engine Works"** 3-phase overview below:
130
+ 1. Authoring (AI-assisted, human-reviewed)
131
+ 2. Engine Initialization (Deterministic analysis)
132
+ 3. Runtime Enforcement (Commit-time)
133
+
134
+ **FOLLOW-UP OFFER**: After showing the 3 phases, offer: "Would you like more detail on any specific aspect?"
135
+
136
+ **NEVER**: Respond with generic "Key Concepts" or custom explanations - use the specific 3-phase content from this file.
137
+
138
+ ---
139
+
140
+ ## Capabilities Reference
141
+
142
+ When user asks "what can I do here", list these capabilities:
143
+
144
+ ### Here Are Some Things I Can Help You With
145
+
146
+ 1. **Add business logic** - Describe requirements in natural language, I'll generate declarative rules (deterministic + AI-driven)
147
+ 2. **Customize the API** - Add custom endpoints for your specific needs
148
+ 3. **Create custom UIs** - Build React apps with `genai-logic genai-add-app --vibe`
149
+ 4. **Add security** - Set up role-based access control with `genai-logic add-auth`
150
+ 5. **Test your logic** - Create Behave tests with requirements traceability
151
+ 6. **Configure Admin UI** - Customize the auto-generated admin interface
152
+ 7. **Query via natural language** - Act as MCP client to read/update data
153
+ 8. **Create B2B APIs** - Complex integration endpoints with partner systems
154
+ 9. **Add events** - Integrate with Kafka, webhooks, or other event systems
155
+ 10. **Customize models** - Add tables, attributes, or derived fields
156
+ 11. **Discovery systems** - Auto-load logic and APIs from discovery folders
157
+
158
+ ---
159
+
160
+ ---
161
+ title: Copilot Instructions for basic_demo GenAI-Logic Project
162
+ Description: Project-level instructions for working with generated projects
163
+ Source: ApiLogicServer-src/prototypes/base/.github/.copilot-instructions.md
164
+ Propagation: CLI create command → created projects (non-basic_demo)
165
+ Instrucions: Changes must be merged from api_logic_server_cli/prototypes/basic_demo/.github - see instructions there
166
+ Usage: AI assistants read this when user opens any created project
167
+ version: 3.1
168
+ changelog:
169
+ - 3.1 (Nov 20, 2025) - Improved activation instructions with visual markers and examples
170
+ - 3.0 (Nov 17, 2025) - Major streamlining: removed duplicate sections, consolidated MCP content, simplified workflows
171
+ - 2.9 (Nov 17, 2025) - MANDATORY training file reading workflow (STOP command)
172
+ - 2.8 (Nov 16, 2025) - Probabilistic Logic support
173
+ ---
174
+
175
+ # GitHub Copilot Instructions for GenAI-Logic (aka API Logic Server) Projects
176
+
177
+ ---
178
+
179
+ ## 🔑 Key Technical Points
180
+
181
+ **Critical Implementation Details:**
182
+
183
+ 1. **Discovery Systems**:
184
+ - **Logic Discovery**: Business rules automatically loaded from `logic/logic_discovery/use_case.py` via `logic/logic_discovery/auto_discovery.py`
185
+ - **API Discovery**: Custom APIs automatically loaded from `api/api_discovery/[service_name].py` via `api/api_discovery/auto_discovery.py`
186
+ - Do NOT manually duplicate rule calls or API registrations
187
+
188
+ 2. **API Record ID Pattern**: When creating records via custom APIs, use `session.flush()` before accessing the ID to ensure it's generated:
189
+ ```python
190
+ session.add(sql_alchemy_row)
191
+ session.flush() # Ensures ID is generated
192
+ record_id = sql_alchemy_row.id
193
+ return {"message": "Success", "record_id": record_id}
194
+ ```
195
+
196
+ 3. **Automatic Business Logic**: All APIs (standard and custom) automatically inherit LogicBank rules without additional code.
197
+
198
+ 4. **CLI Commands**: Use `genai-logic --help` to see all available commands. When CLI commands exist for a task (e.g., `add-auth`, `genai-add-mcp-client`, `genai-add-app`), ALWAYS use them instead of manual configuration - they handle all setup correctly.
199
+
200
+ > **📋 Testing:** For comprehensive testing conventions, patterns, and examples, see `docs/training/testing.md` (555 lines - I'll read this before we create any tests)
201
+
202
+ ---
203
+
204
+ ## Detailed Service Documentation
205
+
206
+ The sections below provide complete details on each service. I'll reference these as needed when we work together.
207
+
208
+ ### `venv` is required
209
+
210
+ To establish the virtual environment:
211
+
212
+ 1. Attempt to find a `venv` folder in the current project directory
213
+ 2. If not found, check parent or grandparent directories
214
+ 3. **If no venv is found:**
215
+ - Ask the user for the venv location, OR
216
+ - Offer to create one using `python3 -m venv venv && source venv/bin/activate && pip install -r requirements.txt`
217
+
218
+ ### Starting the server
219
+
220
+ **IMPORTANT:** Always activate the venv before starting the server.
221
+
222
+ ```bash
223
+ # Activate venv first
224
+ source venv/bin/activate
225
+
226
+ # Then start server
227
+ python api_logic_server_run.py
228
+ # Then open: http://localhost:5656
229
+ ```
230
+
231
+ **Server Management Best Practices:**
232
+ - Before making structural changes (models, logic files), STOP the running server to avoid file locking issues
233
+ - To stop server: `pkill -f "python api_logic_server_run.py"` or use Ctrl+C if running in foreground
234
+ - USER ACTION: After making changes, user restarts server (e.g., `python api_logic_server_run.py &`)
235
+ - Monitor startup output for errors, especially after database/model changes
236
+ - If server fails to start after model changes, check that alembic migrations have been applied
237
+
238
+ ### Adding Business Logic
239
+ `docs/training` explains how to translate Natural Language logic into LogicBank (Python) rules like:
240
+
241
+ ```python
242
+ # Edit: logic/declare_logic.py
243
+ Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal)
244
+ Rule.constraint(validate=Customer, as_condition=lambda row: row.Balance <= row.CreditLimit)
245
+ ```
246
+
247
+ **⚠️ CRITICAL: docs/training/ Folder Organization**
248
+
249
+ The `docs/training/` folder contains ONLY universal, framework-level training materials:
250
+ - ✅ **Universal patterns** → `genai_logic_patterns.md`
251
+ - ✅ **Implementation patterns** → `probabilistic_logic_guide.md`
252
+ - ✅ **Code templates** → `probabilistic_template.py`
253
+ - ✅ **API references** → `.prompt` files (logic_bank_api.prompt, etc.)
254
+
255
+ **DO NOT add project-specific content to docs/training/**:
256
+ - ❌ Project-specific instructions or configurations
257
+ - ❌ Alembic migration guides specific to this project
258
+ - ❌ File structures specific to basic_demo
259
+ - ❌ Copilot instructions that reference specific project paths
260
+
261
+ **WHY:** This folder's content is designed to be reusable across ANY ApiLogicServer project using GenAI. Project-specific content should live in:
262
+ - Logic implementation → `logic/logic_discovery/`
263
+ - Project docs → `docs/` (outside training/)
264
+ - Copilot instructions → `.github/.copilot-instructions.md`
265
+
266
+ See `docs/training/README.md` for complete organization rules.
267
+
268
+ **⚠️ MANDATORY WORKFLOW - BEFORE Implementing ANY Business Logic:**
269
+
270
+ ```
271
+ STOP ✋
272
+
273
+ WHEN USER PROVIDES A LOGIC PROMPT:
274
+
275
+ STEP 1: Read these files (DO THIS FIRST - NOT OPTIONAL):
276
+ 1. docs/training/logic_bank_patterns.prompt (Foundation - READ FIRST)
277
+ 2. docs/training/logic_bank_api.prompt (Deterministic rules - READ SECOND)
278
+ 3. docs/training/probabilistic_logic.prompt (AI/Probabilistic rules - READ THIRD)
279
+
280
+ STEP 2: Parse the prompt following logic_bank_api.prompt instructions:
281
+ - Identify context phrase ("When X", "For Y", "On Z") → creates directory
282
+ - Identify colon-terminated use cases → creates files
283
+ - Follow directory structure rules EXACTLY as specified
284
+
285
+ STEP 3: Create the directory structure and files as instructed
286
+
287
+ STEP 4: Implement the rules following the training patterns
288
+
289
+ ⚠️ CRITICAL - NO EXCEPTIONS:
290
+ - You MUST read all three training files before implementing
291
+ - You MUST follow the directory structure rules in logic_bank_api.prompt
292
+ - You MUST NOT create flat files when context phrase is present
293
+ - DO NOT skip files even if you think you know the pattern
294
+ - These files contain failure patterns learned from production use
295
+
296
+ FAILURE MODE: Creating flat files in logic/logic_discovery/ when prompt has context phrase
297
+ CORRECT: Create logic/logic_discovery/<context_dir>/{__init__.py, use_case_files.py}
298
+ ```
299
+
300
+ **Training File Contents:**
301
+
302
+ 1. **`docs/training/logic_bank_patterns.prompt`** - Foundation patterns for ALL rule types
303
+ - Event handler signatures (row, old_row, logic_row) - REQUIRED READING
304
+ - Logging with logic_row.log() vs app_logger
305
+ - Request Pattern with new_logic_row()
306
+ - Rule API syntax dos and don'ts
307
+ - Common anti-patterns to avoid
308
+
309
+ 2. **`docs/training/logic_bank_api.prompt`** - Deterministic rules API
310
+ - Rule.sum(), Rule.count(), Rule.formula(), Rule.constraint(), etc.
311
+ - Complete API signatures with all parameters
312
+ - References patterns file for implementation details
313
+
314
+ 3. **`docs/training/probabilistic_logic.prompt`** - Probabilistic (AI) rules API
315
+ - populate_ai_values() utility for AI-driven value computation
316
+ - Intelligent selection patterns (supplier optimization, dynamic pricing, route selection)
317
+ - Automatic audit trails and graceful fallbacks when API unavailable
318
+ - References patterns file for general implementations
319
+ - Works seamlessly with deterministic rules
320
+
321
+ **Example Natural Language Logic for basic_demo:**
322
+
323
+ ```text
324
+ Use case: Check Credit
325
+ 1. Customer balance ≤ credit limit
326
+ 2. Customer balance = sum of unshipped Order amount_total
327
+ 3. Order amount_total = sum of Item amount
328
+ 4. Item amount = quantity × unit_price
329
+ 5. Item unit_price = copied from Product unit_price
330
+
331
+ Use case: App Integration
332
+ 1. Send Order to Kafka when date_shipped changes to non-null
333
+ ```
334
+
335
+ **How the Rules Engine Works:**
336
+
337
+ **1. Authoring (AI-assisted, human-reviewed)**
338
+ - You express business intent in natural language (via Copilot or any AI assistant)
339
+ - The AI translates intent into a declarative DSL, under human review
340
+ - Distills path-dependent logic into data-bound rules (table invariants) for automatic re-use
341
+ - Resolves ambiguity using schema and relationships (e.g., copy vs reference)
342
+ - Produces readable rules developers can inspect, edit, debug and version
343
+
344
+ *This is where AI helps — authoring, not execution.*
345
+
346
+ **2. Engine Initialization (Deterministic analysis)**
347
+ - On startup, the non-RETE rule engine loads all rules
348
+ - It computes dependencies deterministically from Rule types (derivations, constraints, actions)
349
+ - Execution order is derived once, not from code paths
350
+
351
+ No compilation. No dependencies-from-pattern-matching. No inference from runtime behavior.
352
+
353
+ **3. Runtime Enforcement (Commit-time)**
354
+ - Rules execute at transaction commit via SQLAlchemy commit events
355
+ - All writes — APIs, workflows, UIs, agents — pass through the same rule set
356
+ - Dependencies are already known; execution is deterministic and efficient
357
+ - **No rule is "called." No path can bypass enforcement.**
358
+ - Non-RETE optimizations: pruning, adjustment logic, delta-based aggregations
359
+ - **Cascading via old_row tracking** - When Order.customer_id changes, adjusts BOTH old and new Customer.balance
360
+
361
+ **The Key Developer Insight:**
362
+
363
+ You declare invariants on data. You don't wire rules into flows. Invocation is automatic, on commit. The engine enforces them — everywhere, automatically, at commit.
364
+
365
+ **Why Declarative Rules Matter:**
366
+
367
+ LogicBank provides **44X code reduction** (5 lines vs 220+ procedural) with:
368
+ - **Automatic ordering** - add rules anywhere that makes sense, confident they'll run in the right order
369
+ - **Understanding intent** - you see WHAT it does (business rules) vs HOW (procedural steps)
370
+ - **Maintenance** - no need to find insertion points or trace execution paths
371
+
372
+ **Why the Rules Engine is a Correctness Guarantee:**
373
+
374
+ The "2 critical bugs" that even AI-generated procedural code missed:
375
+ 1. **Changing Order.customer_id** - procedural code failed to adjust BOTH the old and new customer balances
376
+ 2. **Changing Item.product_id** - procedural code failed to re-copy the unit_price from the new product
377
+
378
+ These bugs illustrate why declarative rules are **mandatory, not optional**. Even AI-generated procedural code requires explicit handlers for EVERY possible change path. It's easy to miss:
379
+ - Foreign key changes affecting multiple parents
380
+ - Transitive dependencies through multiple tables
381
+ - Where clause conditions that include/exclude rows
382
+
383
+ The rules engine eliminates this entire class of bugs by automatically handling all change paths.
384
+
385
+ See `logic/declarative-vs-procedural-comparison.md` for complete analysis.
386
+
387
+ ### Discovery Systems
388
+
389
+ **IMPORTANT**: The project uses automated discovery systems that:
390
+
391
+ **Logic Discovery:**
392
+ 1. **Automatically loads business logic** from `logic/logic_discovery/*.py`
393
+ * **CRITICAL: Always create separate files named for each use case** (e.g., `check_credit.py`, `app_integration.py`)
394
+ * **Never put multiple use cases in `use_case.py`** - that file is for templates/examples only
395
+ 2. **Discovers rules at startup** via `logic/logic_discovery/auto_discovery.py`
396
+ 3. **No manual rule loading required** - the `discover_logic()` function automatically finds and registers rules
397
+
398
+ **API Discovery:**
399
+ 1. **Automatically loads custom APIs** from `api/api_discovery/[service_name].py`
400
+ 2. **Discovers services at startup** via `api/api_discovery/auto_discovery.py` (called from `api/customize_api.py`)
401
+ 3. **No manual API registration required** - services are automatically discovered and exposed
402
+
403
+ **Do NOT duplicate** by calling them manually. The discovery systems handle this automatically.
404
+
405
+ **Implementation Locations**:
406
+ - Business rules: `logic/logic_discovery/use_case.py`
407
+ - Custom APIs: `api/api_discovery/[service_name].py`
408
+ - System automatically discovers and loads both
409
+
410
+ **Pattern**:
411
+ ```python
412
+ # logic/logic_discovery/use_case.py
413
+ def declare_logic():
414
+ """Business logic rules for the application"""
415
+ Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total)
416
+ Rule.constraint(validate=Customer, as_condition=lambda row: row.balance <= row.credit_limit)
417
+ # ... other rules
418
+ ```
419
+
420
+ **PATTERN RECOGNITION for Business Logic**:
421
+ When users provide natural language with multiple use cases like:
422
+ - "on Placing Orders, Check Credit" + "Use case: App Integration"
423
+
424
+ **ALWAYS create separate files**:
425
+ - `logic/logic_discovery/check_credit.py` - for credit checking rules
426
+ - `logic/logic_discovery/app_integration.py` - for integration rules
427
+
428
+ **NEVER put everything in `use_case.py`** - that defeats the discovery system purpose.
429
+
430
+ ### MCP Integration
431
+
432
+ **You (GitHub Copilot) can serve as an MCP client** to query and update database entities using natural language!
433
+
434
+ #### MCP Discovery Endpoint (CRITICAL)
435
+
436
+ **ALWAYS start with the standard MCP discovery endpoint:**
437
+
438
+ ```bash
439
+ curl -X GET "http://localhost:5656/.well-known/mcp.json"
440
+ ```
441
+
442
+ This endpoint returns:
443
+ - **Available resources** - Customer, Order, Item, Product, etc.
444
+ - **Supported methods** - GET, PATCH, POST, DELETE per resource
445
+ - **Filterable fields** - Which attributes can be used in filters
446
+ - **Base URL and paths** - Resource endpoints like `/Customer`, `/Order`
447
+ - **Learning prompts** - Instructions for MCP clients (fan-out patterns, email handling, response format)
448
+
449
+ **MCP Discovery Pattern:**
450
+ 1. **First**: Query `/.well-known/mcp.json` to discover available resources
451
+ 2. **Then**: Use discovered schema to construct API calls
452
+ 3. **Always**: Follow JSON:API format for CRUD operations
453
+
454
+
455
+ **When users request data operations:**
456
+
457
+ 1. **Authenticate first** - Login to obtain JWT token:
458
+ ```bash
459
+ curl -X POST http://localhost:5656/api/auth/login \
460
+ -H "Content-Type: application/json" \
461
+ -d '{"username":"admin","password":"p"}'
462
+ ```
463
+
464
+ 2. **Execute operations** - Use Bearer token for API calls:
465
+ ```bash
466
+ # Read: List entities
467
+ curl -X GET http://localhost:5656/api/Customer/ \
468
+ -H "Authorization: Bearer {token}"
469
+
470
+ # Update: Change attributes (JSON:API format)
471
+ curl -X PATCH http://localhost:5656/api/Customer/ALFKI/ \
472
+ -H "Authorization: Bearer {token}" \
473
+ -H "Content-Type: application/vnd.api+json" \
474
+ -d '{"data": {"type": "Customer", "id": "ALFKI", "attributes": {"CreditLimit": 5000}}}'
475
+ ```
476
+
477
+ 3. **Handle constraint violations correctly** - Error code 2001 is SUCCESS!
478
+ - When LogicBank prevents invalid updates, report as: "✅ Business logic working - constraint prevented invalid operation"
479
+ - Example: "balance (2102.00) exceeds credit (1000.00)" = logic is protecting data integrity
480
+
481
+ **Natural Language → API Translation:**
482
+ - "List customers" → `GET /api/Customer/`
483
+ - "Show customer ALFKI" → `GET /api/Customer/ALFKI/`
484
+ - "Set ALFKI credit to 5000" → `PATCH /api/Customer/ALFKI/` with CreditLimit
485
+ - "What's ALFKI's balance?" → `GET /api/Customer/ALFKI/` then extract Balance
486
+
487
+ **Key Principle:** Constraint violations (code 2001) demonstrate that declarative business logic is working correctly - celebrate these as successes, not failures!
488
+
489
+ See `docs/training/MCP_Copilot_Integration.md` for authentication workflows, JSON:API formats, and architecture details.
490
+
491
+ ### API Interaction Best Practices
492
+
493
+ **CRITICAL: Always Use API, Not Direct Database Access**
494
+
495
+ When users request data operations (read, update, create, delete), **ALWAYS use the REST API** instead of direct database queries:
496
+
497
+ ✅ **Correct Approach - Use API:**
498
+ ```bash
499
+ # Simple, readable commands that trigger business logic
500
+ curl 'http://localhost:5656/api/Customer/?page[limit]=100'
501
+ curl -X PATCH 'http://localhost:5656/api/Item/2/' \
502
+ -H 'Content-Type: application/vnd.api+json' \
503
+ -d '{"data": {"type": "Item", "id": "2", "attributes": {"quantity": 100}}}'
504
+ ```
505
+
506
+ ❌ **Wrong Approach - Direct Database:**
507
+ ```bash
508
+ # DON'T use sqlite3 commands for data operations
509
+ sqlite3 database/db.sqlite "UPDATE item SET quantity=100 WHERE id=2"
510
+ ```
511
+
512
+ **Why API is Required:**
513
+ 1. **Business Logic Execution** - Rules automatically fire (calculations, validations, constraints)
514
+ 2. **Data Integrity** - Cascading updates handled correctly
515
+ 3. **Audit Trail** - Operations logged through proper channels
516
+ 4. **Security** - Authentication/authorization enforced
517
+ 5. **Testing Reality** - Tests actual system behavior
518
+
519
+ **Server Startup for API Operations:**
520
+
521
+ When server needs to be started for API operations:
522
+
523
+ ```bash
524
+ # Option 1: Background process (for interactive testing)
525
+ python api_logic_server_run.py &
526
+ sleep 5 # Wait for full startup (not 3 seconds - too short!)
527
+
528
+ # Option 2: Use existing terminal/process
529
+ # Check if already running: lsof -i :5656
530
+ ```
531
+
532
+ **Common Mistakes to Avoid:**
533
+
534
+ 1. ❌ **Insufficient startup wait**: `sleep 3` often fails
535
+ - ✅ Use: `sleep 5` or check with `curl` in retry loop
536
+
537
+ 2. ❌ **Complex inline Python**: Piping JSON to `python3 -c` with complex list comprehensions
538
+ - ✅ Use: Simple `curl` commands, pipe to `jq` for filtering, or save to file first
539
+
540
+ 3. ❌ **Database queries for CRUD**: Using `sqlite3` commands
541
+ - ✅ Use: API endpoints that trigger business logic
542
+
543
+ **Simple API Query Patterns:**
544
+
545
+ ```bash
546
+ # Get all records (simple, reliable)
547
+ curl 'http://localhost:5656/api/Customer/'
548
+
549
+ # Get specific record by ID
550
+ curl 'http://localhost:5656/api/Customer/1/'
551
+
552
+ # Get related records (follow relationships)
553
+ curl 'http://localhost:5656/api/Customer/1/OrderList'
554
+
555
+ # Filter results (use bracket notation)
556
+ curl 'http://localhost:5656/api/Customer/?filter[name]=Alice'
557
+
558
+ # Limit results
559
+ curl 'http://localhost:5656/api/Customer/?page[limit]=10'
560
+ ```
561
+
562
+ **Parsing JSON Responses:**
563
+
564
+ ```bash
565
+ # Simple: Pipe to python -m json.tool for pretty printing
566
+ curl 'http://localhost:5656/api/Customer/' | python3 -m json.tool
567
+
568
+ # Better: Use jq if available
569
+ curl 'http://localhost:5656/api/Customer/' | jq '.data[] | {id, name: .attributes.name}'
570
+
571
+ # Alternative: Save to file first, then parse
572
+ curl 'http://localhost:5656/api/Customer/' > customers.json
573
+ python3 -c "import json; data=json.load(open('customers.json')); print(data['data'][0])"
574
+ ```
575
+
576
+ **Key Principle**: The API is not just a convenience - it's the **only correct way** to interact with data because it ensures business logic executes properly.
577
+
578
+ ### Automated Testing
579
+
580
+ **⚠️ BEFORE Creating Tests:**
581
+
582
+ ```
583
+ STOP ✋
584
+ READ docs/training/testing.md FIRST (555 lines - comprehensive guide)
585
+
586
+ This contains EVERY bug pattern from achieving 11/11 test success:
587
+ - Rule #0: Test Repeatability (timestamps for uniqueness)
588
+ - Rule #0.5: Behave Step Ordering (specific before general)
589
+ - Top 5 Critical Bugs (common AI mistakes)
590
+ - Filter format: filter[column]=value (NOT OData)
591
+ - No circular imports (API only)
592
+ - Null-safe constraints
593
+ - Fresh test data (timestamps for uniqueness)
594
+
595
+ THEN create tests following patterns exactly.
596
+ ```
597
+
598
+ **Why This Matters:** AI-generated tests fail 80% of the time without reading this guide first. The training material documents every common mistake (circular imports, wrong filter format, null-unsafe constraints, step ordering, etc.) with exact fixes. This guide achieved 11/11 test success (100%) and contains all discovered patterns.
599
+
600
+ **`docs/training/testing.md`** explains how to create Behave tests from declarative rules, execute test suites, and generate automated documentation with complete logic traceability.
601
+
602
+ **Key capabilities:**
603
+ - **Create tests from rules** - Analyze declarative rules to generate appropriate test scenarios
604
+ - **Execute test suite** - Run all tests with one command (Launch Configuration: "Behave Run")
605
+ - **Generate documentation** - Auto-create wiki reports showing requirements, tests, rules used, and execution traces
606
+ - **Requirements traceability** - Complete chain from business requirement → test → declarative rule → execution log
607
+
608
+ **The Innovation:** Unlike traditional testing, Behave Logic Reports show **which declarative rules fired** during each test, providing complete transparency from requirement to execution. This solves the 44X advantage in testing - tests verify "what" (business rules) not "how" (procedural code).
609
+
610
+ See `test/api_logic_server_behave/` for examples and [published report](https://apilogicserver.github.io/Docs/Behave-Logic-Report/).
611
+
612
+ **Common Mistakes to Avoid (from testing.md):**
613
+ 1. ❌ Wrong filter: `filter="name eq 'Alice'"` → ✅ Use: `filter[name]="Alice"`
614
+ 2. ❌ Importing logic/database modules → ✅ Import only: behave, requests, test_utils
615
+ 3. ❌ Unsafe constraints: `row.x <= row.y` → ✅ Use: `row.x is None or row.y is None or row.x <= row.y`
616
+ 4. ❌ Step execution: `step_impl.execute_step()` → ✅ Use: `context.execute_steps('when Step')`
617
+ 5. ❌ Reusing test data → ✅ Create fresh with: `f"{name} {int(time.time()*1000)}"`
618
+
619
+ **For detailed test creation patterns, see `docs/training/testing.md` which documents all critical rules including Rule #0.5 (Behave Step Ordering).**
620
+
621
+ #### Critical Learnings: Behave Logic Report Generation
622
+
623
+ **PROBLEM**: Reports not showing logic details for test scenarios.
624
+
625
+ **ROOT CAUSES DISCOVERED**:
626
+
627
+ 1. **Empty behave.log** (Most Common Issue)
628
+ - ❌ Running: `python behave_run.py`
629
+ - ✅ Must run: `python behave_run.py --outfile=logs/behave.log`
630
+ - Without `--outfile`, behave.log remains empty (0 bytes) and report has no content
631
+
632
+ 2. **Scenario Name Mismatch**
633
+ - Log files must match scenario names from .feature file
634
+ - ❌ Using custom names: `scenario_name = f'B2B Order - {quantity} {product_name}'`
635
+ - ✅ Use actual scenario: `scenario_name = context.scenario.name`
636
+ - Report generator truncates to 25 chars and looks for matching .log files
637
+
638
+ 3. **Report Generator Logic Bug**
639
+ - Original code only showed logic when blank line followed "Then" step
640
+ - Only worked for ~30% of scenarios (those with blank lines in behave.log)
641
+ - ✅ Fixed: Trigger logic display when next scenario starts OR at end of file
642
+
643
+ **CORRECT PATTERN FOR WHEN STEPS**:
644
+
645
+ ```python
646
+ @when('B2B order placed for "{customer_name}" with {quantity:d} {product_name}')
647
+ def step_impl(context, customer_name, quantity, product_name):
648
+ """
649
+ Phase 2: CREATE using OrderB2B API - Tests OrderB2B integration
650
+ """
651
+ scenario_name = context.scenario.name # ← CRITICAL: Use actual scenario name
652
+ test_utils.prt(f'\n{scenario_name}\n', scenario_name)
653
+
654
+ # ... test implementation ...
655
+ ```
656
+
657
+ **WORKFLOW FOR REPORT GENERATION**:
658
+
659
+ ```bash
660
+ # 1. Run tests WITH outfile to generate behave.log
661
+ python behave_run.py --outfile=logs/behave.log
662
+
663
+ # 2. Generate report (reads behave.log + scenario_logic_logs/*.log)
664
+ python behave_logic_report.py run
665
+
666
+ # 3. View report
667
+ open reports/Behave\ Logic\ Report.md
668
+ ```
669
+
670
+ **WHAT THE REPORT SHOWS**:
671
+ - Each scenario gets a `<details>` section with:
672
+ - **Rules Used**: Which declarative rules fired (numbered list)
673
+ - **Logic Log**: Complete trace showing before→after values for all adjustments
674
+ - Demonstrates the 44X code reduction by showing rule automation
675
+
676
+ **LOGIC LOG FORMATTING**:
677
+
678
+ **When user says "show me the logic log"**: Display the complete logic execution from the most recent terminal output, showing the full trace from "Logic Phase: ROW LOGIC" through "Logic Phase: COMPLETE" with all row details intact (do NOT use grep commands to extract). Include:
679
+ - Complete Logic Phase sections (ROW LOGIC, COMMIT LOGIC, AFTER_FLUSH LOGIC, COMPLETE)
680
+ - All rule execution lines with full row details
681
+ - "These Rules Fired" summary section
682
+ - Format as code block for readability
683
+
684
+ When displaying logic logs to users, format them with proper hierarchical indentation like the debug console (see https://apilogicserver.github.io/Docs/Logic-Debug/):
685
+
686
+ ```
687
+ Logic Phase: ROW LOGIC (session=0x...)
688
+ ..Item[None] {Insert - client} id: None, order_id: 1, product_id: 6, quantity: 10
689
+ ..Item[None] {Formula unit_price} unit_price: [None-->] 105.0
690
+ ....SysSupplierReq[None] {Insert - Supplier AI Request} product_id: 6
691
+ ....SysSupplierReq[None] {Event - calling AI} chosen_unit_price: [None-->] 105.0
692
+ ..Item[None] {Formula amount} amount: [None-->] 1050.0
693
+ ..Item[None] {adjust parent Order.amount_total}
694
+ ....Order[1] {Update - Adjusting order: amount_total} amount_total: [300.0-->] 1350.0
695
+ ```
696
+
697
+ **Key formatting rules:**
698
+ - `..` prefix = nesting level (2 dots = parent, 4 dots = child/nested object, 6 dots = deeper nesting)
699
+ - **ONE LINE per rule execution** - no line wrapping
700
+ - Each line shows: `Class[id] {action/reason} key_attributes`
701
+ - Value changes shown as: `[old_value-->] new_value`
702
+ - Hierarchical indentation (dots) shows call depth and parent-child relationships
703
+ - Only show relevant attributes, not all row details
704
+
705
+ **EXTRACTING CLEAN LOGIC LOGS**:
706
+
707
+ To get properly formatted logs (one line per rule, no wrapping), use this command:
708
+
709
+ ```bash
710
+ # Extract clean logic log from server.log
711
+ grep -A 100 "Logic Phase:.*ROW LOGIC" server.log | \
712
+ awk -F' row: ' '{print $1}' | \
713
+ grep -E "^\.\.|^Logic Phase:" | \
714
+ head -50
715
+ ```
716
+
717
+ This removes verbose session/row details and prevents line wrapping.
718
+
719
+ **DEBUGGING TIPS**:
720
+
721
+ ```bash
722
+ # Check if behave.log has content
723
+ ls -lh logs/behave.log # Should be several KB, not 0 bytes
724
+
725
+ # Check if scenario logs exist with correct names
726
+ ls logs/scenario_logic_logs/ | head -10
727
+
728
+ # Count detail sections in report (should equal number of scenarios)
729
+ grep -c "<details markdown>" reports/Behave\ Logic\ Report.md
730
+
731
+ # View a specific scenario's log directly
732
+ cat logs/scenario_logic_logs/Delete_Item_Reduces_Order.log
733
+ ```
734
+
735
+ **KEY INSIGHT**: The report generator uses a two-step process:
736
+ 1. Reads behave.log for scenario structure (Given/When/Then steps)
737
+ 2. Matches scenario names to .log files in scenario_logic_logs/
738
+ 3. Injects logic details at the right location in the report
739
+
740
+ If scenario names don't match between behave.log and .log filenames, logic details won't appear!
741
+
742
+ ### Adding MCP UI
743
+
744
+ The API is automatically MCP-enabled. The project includes a comprehensive MCP client executor at `integration/mcp/mcp_client_executor.py`, but to enable the **user interface** for MCP requests, you must run this command:
745
+
746
+ ```bash
747
+ genai-logic genai-add-mcp-client
748
+ ```
749
+
750
+ **CRITICAL DISTINCTION**:
751
+ - **`integration/mcp/mcp_client_executor.py`** = MCP processing engine (already exists)
752
+ - **`genai-logic genai-add-mcp-client`** = Command to add SysMcp table and UI infrastructure (must be run)
753
+
754
+ **When users ask to "Create the MCP client executor"**, they mean run the `genai-logic genai-add-mcp-client` command, NOT recreate the existing processing engine.
755
+
756
+ This command adds:
757
+ 1. **SysMcp table** for business users to enter natural language requests
758
+ 2. **Admin App integration** for MCP request interface
759
+ 3. **Database infrastructure** for MCP client operations
760
+
761
+ ### Configuring Admin UI
762
+
763
+ This is built when project is created - no need to add it.
764
+ Customize by editing the underlying yaml.
765
+
766
+ ```yaml
767
+ # Edit: ui/admin/admin.yaml
768
+ resources:
769
+ Customer:
770
+ attributes:
771
+ - name: CompanyName
772
+ search: true
773
+ sort: true
774
+ ```
775
+
776
+ ### Create and Customize React Apps
777
+
778
+ **REQUIRED METHOD**: Complete customization is provided by generating a React Application (requires OpenAI key, Node):
779
+
780
+ **DO NOT use `create-react-app` or `npx create-react-app`**
781
+ **ALWAYS use this command instead:**
782
+
783
+ ```bash
784
+ # Create: ui/admin/my-app-name
785
+ genai-logic genai-add-app --app-name=my-app-name --vibe
786
+ ```
787
+
788
+ Then, `npm install` and `npm start`
789
+
790
+ Temporary restriction: security must be disabled.
791
+
792
+ **IMPORTANT**: When working with React apps, ALWAYS read `docs/training` first. This file contains critical data access provider configuration that was built when the project was created. The data provider handles JSON:API communication and record context - ignore this at your peril.
793
+
794
+ Customize using CoPilot chat, with `docs/training`.
795
+
796
+ #### React Component Development Best Practices
797
+
798
+ **Critical Pattern for List/Card Views**: When implementing custom views (like card layouts) in React Admin components:
799
+
800
+ 1. **Use `useListContext()` correctly**: Access `data` as an array, not as an object with `ids`
801
+ ```javascript
802
+ // CORRECT Pattern:
803
+ const { data, isLoading } = useListContext();
804
+ return (
805
+ <Grid container spacing={2}>
806
+ {data?.map(record => (
807
+ <Grid item key={record.id}>
808
+ <CustomCard record={record} />
809
+ </Grid>
810
+ ))}
811
+ </Grid>
812
+ );
813
+
814
+ // AVOID: Trying to use data[id] pattern - this is for older React Admin versions
815
+ ```
816
+
817
+
818
+ 2. **Component Naming Consistency**: Ensure component names match their usage in JSX - mismatched names cause runtime errors.
819
+
820
+ 3. **Simple Error Handling**: Use straightforward loading states rather than complex error checking:
821
+ ```javascript
822
+ if (isLoading) return <div>Loading...</div>;
823
+ ```
824
+
825
+ 4. 🃏 Card View Action Links (Show, Edit, Delete) **IMPORTANT:** All card views (e.g., Product cards) must include action links or buttons for **Show**, **Edit**, and **Delete** for each record (not just the display fields), matching the functionality of the table/list view.
826
+
827
+
828
+ **Common Mistakes to Avoid**:
829
+ - Using `{ data, ids }` destructuring and trying to map over `ids` - this pattern is outdated
830
+ - Creating complex error handling when simple loading checks suffice
831
+ - Not referencing existing working implementations before creating new patterns
832
+
833
+ ### Security - Role-Based Access Control
834
+
835
+ Configure:
836
+ ```
837
+ genai-logic add-auth --provider-type=sql --db-url=
838
+ genai-logic add-auth --provider-type=sql --db_url=postgresql://postgres:p@localhost/authdb
839
+
840
+ genai-logic add-auth --provider-type=keycloak --db-url=localhost
841
+ genai-logic add-auth --provider-type=keycloak --db-url=hardened
842
+
843
+ genai-logic add-auth --provider-type=None # to disable
844
+ ```
845
+
846
+ Keycloak quick start [(more information here:)](https://apilogicserver.github.io/Docs/Security-Keycloak/)
847
+ ```bash
848
+ cd devops/keycloak
849
+ docker compose up
850
+ genai-logic add-auth --provider-type=keycloak --db-url=localhost
851
+ ```
852
+
853
+ For more on KeyCloak: https://apilogicserver.github.io/Docs/Security-Keycloak/
854
+
855
+ Declaration:
856
+ ```python
857
+ # Edit: security/declare_security.py
858
+ Grant(on_entity=Customer, to_role=sales, filter=lambda: Customer.SalesRep == current_user())
859
+ ```
860
+
861
+
862
+ #### Testing with Security Enabled
863
+
864
+ **CRITICAL:** When `SECURITY_ENABLED=True`, test code must obtain and include JWT authentication tokens.
865
+
866
+ **Pattern for test steps:**
867
+ ```python
868
+ from pathlib import Path
869
+ import os
870
+ from dotenv import load_dotenv
871
+
872
+ # Load config to check SECURITY_ENABLED
873
+ config_path = Path(__file__).parent.parent.parent.parent.parent / 'config' / 'default.env'
874
+ load_dotenv(config_path)
875
+
876
+ # Cache for auth token (obtained once per test session)
877
+ _auth_token = None
878
+
879
+ def get_auth_token():
880
+ """Login and get JWT token if security is enabled"""
881
+ global _auth_token
882
+
883
+ if _auth_token is not None:
884
+ return _auth_token
885
+
886
+ # Login with default admin credentials
887
+ login_url = f'{BASE_URL}/api/auth/login'
888
+ login_data = {'username': 'admin', 'password': 'p'}
889
+
890
+ response = requests.post(login_url, json=login_data)
891
+ if response.status_code == 200:
892
+ _auth_token = response.json().get('access_token')
893
+ return _auth_token
894
+ else:
895
+ raise Exception(f"Login failed: {response.status_code}")
896
+
897
+ def get_headers():
898
+ """Get headers including auth token if security is enabled"""
899
+ security_enabled = os.getenv('SECURITY_ENABLED', 'false').lower() not in ['false', 'no']
900
+
901
+ headers = {'Content-Type': 'application/json'}
902
+
903
+ if security_enabled:
904
+ token = get_auth_token()
905
+ if token:
906
+ headers['Authorization'] = f'Bearer {token}'
907
+
908
+ return headers
909
+
910
+ # Use in all API requests
911
+ response = requests.post(url=api_url, json=data, headers=get_headers())
912
+ ```
913
+
914
+ **Key points:**
915
+ - Tests DO NOT automatically include auth headers - you must code this pattern
916
+ - Token is cached to avoid repeated logins during test session
917
+ - Pattern works for both `SECURITY_ENABLED=True` and `SECURITY_ENABLED=False`
918
+ - See `test/api_logic_server_behave/features/steps/order_processing_steps.py` for complete example
919
+ ### Adding Custom API Endpoints
920
+
921
+ For simple endpoints:
922
+ ```python
923
+ # Edit: api/customize_api.py
924
+ @app.route('/api/custom-endpoint')
925
+ def my_endpoint():
926
+ return {"message": "Custom endpoint"}
927
+ ```
928
+
929
+ ### Creating Advanced B2B Integration APIs with Natural Language
930
+
931
+ Users can create sophisticated custom API endpoints for B2B integration using natural language. The system automatically generates and discovers:
932
+
933
+ 1. **Custom API Service** (`api/api_discovery/[service_name].py`) - automatically discovered by `api/api_discovery/auto_discovery.py`
934
+ 2. **Row Dict Mapper** (`integration/row_dict_maps/[MapperName].py`)
935
+
936
+ **Example Implementation**: This project includes a working **OrderB2B API** that demonstrates the complete pattern:
937
+ - **API**: `api/api_discovery/order_b2b_service.py`
938
+ - **Mapper**: `integration/row_dict_maps/OrderB2BMapper.py`
939
+ - **Test Cases**: `test_requests.http` and `test_b2b_order_api.py`
940
+
941
+ **Pattern Recognition**: When users describe B2B integration scenarios involving:
942
+ - External partner data formats (✅ Account → Customer lookup)
943
+ - Field aliasing/renaming (✅ "Name" → Product.name, "QuantityOrdered" → Item.quantity)
944
+ - Nested data structures (✅ Items array handling)
945
+ - Lookups and joins (✅ Customer by name, Product by name)
946
+ - Data transformation (✅ External format to internal models)
947
+
948
+ Generate both the API service and corresponding Row Dict Mapper following these patterns:
949
+
950
+ **API Service Template** (`api/api_discovery/[service_name].py`) - Keep it concise:
951
+ ```python
952
+ from flask import request
953
+ from safrs import jsonapi_rpc
954
+ import safrs
955
+ from integration.row_dict_maps.OrderB2BMapper import OrderB2BMapper
956
+ import logging
957
+
958
+ app_logger = logging.getLogger("api_logic_server_app")
959
+
960
+ def add_service(app, api, project_dir, swagger_host: str, PORT: str, method_decorators = []):
961
+ api.expose_object(OrderB2BEndPoint)
962
+
963
+ class OrderB2BEndPoint(safrs.JABase):
964
+ @classmethod
965
+ @jsonapi_rpc(http_methods=["POST"])
966
+ def OrderB2B(self, *args, **kwargs): # yaml comment => swagger description
967
+ """ # yaml creates Swagger description
968
+ args :
969
+ data:
970
+ Account: "Alice"
971
+ Notes: "Rush order for Q4 promotion"
972
+ Items :
973
+ - Name: "Widget"
974
+ QuantityOrdered: 5
975
+ - Name: "Gadget"
976
+ QuantityOrdered: 3
977
+ ---
978
+
979
+ Creates B2B orders from external partner systems with automatic lookups and business logic.
980
+ Features automatic customer/product lookups by name, unit price copying,
981
+ amount calculations, customer balance updates, and credit limit validation.
982
+ """
983
+ db = safrs.DB
984
+ session = db.session
985
+
986
+ try:
987
+ mapper_def = OrderB2BMapper()
988
+ request_dict_data = request.json["meta"]["args"]["data"]
989
+
990
+ app_logger.info(f"OrderB2B: Processing order for account: {request_dict_data.get('Account')}")
991
+
992
+ sql_alchemy_row = mapper_def.dict_to_row(row_dict=request_dict_data, session=session)
993
+
994
+ session.add(sql_alchemy_row)
995
+ session.flush() # Ensures ID is generated before accessing it
996
+
997
+ order_id = sql_alchemy_row.id
998
+ customer_name = sql_alchemy_row.customer.name if sql_alchemy_row.customer else "Unknown"
999
+ item_count = len(sql_alchemy_row.ItemList)
1000
+
1001
+ return {
1002
+ "message": "B2B Order created successfully",
1003
+ "order_id": order_id,
1004
+ "customer": customer_name,
1005
+ "items_count": item_count
1006
+ }
1007
+
1008
+ except Exception as e:
1009
+ app_logger.error(f"OrderB2B: Error creating order: {str(e)}")
1010
+ session.rollback()
1011
+ return {"error": "Failed to create B2B order", "details": str(e)}, 400
1012
+ ```
1013
+
1014
+ **IMPORTANT**: The project includes a working B2B integration example:
1015
+ - **API Endpoint**: `OrderB2BEndPoint.OrderB2B` - Creates orders from external partner format
1016
+ - **Error Handling**: Proper exception handling with session rollback for failed operations
1017
+ - **Business Logic**: Automatic inheritance of all LogicBank rules (pricing, calculations, validation)
1018
+ - **Testing**: Comprehensive test suite demonstrating success and error scenarios
1019
+ - **Documentation**: Professional Swagger docs with YAML examples using real database data
1020
+
1021
+ When creating new B2B APIs, follow this proven pattern:
1022
+ - Use `session.flush()` when you need generated IDs before commit
1023
+ - Include proper error handling with try/catch and session.rollback()
1024
+ - Provide meaningful success messages with key information (ID, customer, item count)
1025
+ - Use YAML format in docstrings for clean Swagger documentation
1026
+ - Always use actual database data in examples (check with sqlite3 queries)
1027
+
1028
+ **AI Anti-Patterns to Avoid**:
1029
+ - **Don't assume CRUD operations**: If user asks for "create order API", only implement POST/insert (ask if they need GET/PUT/DELETE)
1030
+ - **Don't add "enterprise" features** unless specifically requested:
1031
+ - Detailed logging/monitoring beyond basic debugging
1032
+ - Complex response objects with metadata
1033
+ - Extensive documentation/comments
1034
+ - HTTP status code handling beyond defaults
1035
+ - **Don't import unused libraries**: Skip `logging`, `jsonify`, etc. unless actually needed
1036
+ - **Don't over-engineer**: Simple success messages beat complex response objects
1037
+
1038
+ **Swagger Examples Must Use Real Data**:
1039
+ When creating YAML docstring examples, use actual database data. Check first:
1040
+ ```bash
1041
+ sqlite3 database/db.sqlite "SELECT name FROM customer LIMIT 3;"
1042
+ sqlite3 database/db.sqlite "SELECT name FROM product LIMIT 3;"
1043
+ ```
1044
+
1045
+ **Getting Sample Data for Tests**:
1046
+ ```bash
1047
+ # Check actual customer names
1048
+ sqlite3 database/db.sqlite "SELECT name FROM customer LIMIT 5;"
1049
+
1050
+ # Check actual product names
1051
+ sqlite3 database/db.sqlite "SELECT name FROM product LIMIT 5;"
1052
+ ```
1053
+ Never assume data from other databases (like Northwind's "ALFKI") - always use the current project's actual data.
1054
+
1055
+ **Row Dict Mapper Template** (`integration/row_dict_maps/[MapperName].py`):
1056
+ ```python
1057
+ from integration.system.RowDictMapper import RowDictMapper
1058
+ from database import models
1059
+
1060
+ class OrderB2BMapper(RowDictMapper):
1061
+ def __init__(self):
1062
+ """
1063
+ B2B Order API Mapper for external partner integration.
1064
+
1065
+ Maps external B2B format to internal Order/Item structure:
1066
+ - 'Account' field maps to Customer lookup by name
1067
+ - 'Notes' field maps directly to Order notes
1068
+ - 'Items' array with 'Name' and 'QuantityOrdered' maps to Item records
1069
+ """
1070
+ mapper = super(OrderB2BMapper, self).__init__(
1071
+ model_class=models.Order,
1072
+ alias="Order",
1073
+ fields=[
1074
+ (models.Order.notes, "Notes"),
1075
+ # customer_id will be set via parent lookup
1076
+ # amount_total will be calculated by business logic
1077
+ # CreatedOn will be set by business logic
1078
+ ],
1079
+ parent_lookups=[
1080
+ (models.Customer, [(models.Customer.name, 'Account')])
1081
+ ],
1082
+ related=[
1083
+ ItemB2BMapper()
1084
+ ]
1085
+ )
1086
+ return mapper
1087
+
1088
+ class ItemB2BMapper(RowDictMapper):
1089
+ def __init__(self):
1090
+ """
1091
+ B2B Item Mapper for order line items.
1092
+
1093
+ Maps external item format to internal Item structure:
1094
+ - 'Name' field maps to Product lookup by name
1095
+ - 'QuantityOrdered' maps to Item quantity
1096
+ """
1097
+ mapper = super(ItemB2BMapper, self).__init__(
1098
+ model_class=models.Item,
1099
+ alias="Items",
1100
+ fields=[
1101
+ (models.Item.quantity, "QuantityOrdered"),
1102
+ # unit_price will be copied from product by business logic
1103
+ # amount will be calculated by business logic (quantity * unit_price)
1104
+ ],
1105
+ parent_lookups=[
1106
+ (models.Product, [(models.Product.name, 'Name')])
1107
+ ],
1108
+ isParent=False
1109
+ )
1110
+ return mapper
1111
+ ```
1112
+
1113
+ **Key Components for Natural Language Processing**:
1114
+ - **Field Aliasing**: `(models.Table.field, "ExternalName")`
1115
+ - **Parent Lookups**: `(models.ParentTable, [(models.ParentTable.lookup_field, 'ExternalKey')])`
1116
+ - **Related Entities**: Nested RowDictMapper instances for child records
1117
+ - **Automatic Joins**: System handles foreign key relationships automatically
1118
+
1119
+ **Business Logic Integration**: All generated APIs automatically inherit the full LogicBank rule engine through the discovery systems (`logic/logic_discovery/auto_discovery.py` and `api/api_discovery/auto_discovery.py`), ensuring data integrity, calculations, and constraints without additional code. Rules are automatically loaded from `logic/logic_discovery/use_case.py` and APIs from `api/api_discovery/[service_name].py` at startup.
1120
+
1121
+ **Testing B2B APIs**: The project includes comprehensive testing infrastructure:
1122
+ - **REST Client Tests**: `test_requests.http` - Test directly in VS Code with REST Client extension
1123
+ - **Python Test Suite**: `test_b2b_order_api.py` - Automated testing with requests library
1124
+ - **Swagger UI**: `http://localhost:5656/api` - Interactive API testing and documentation
1125
+ - **Sample Requests**: `sample_b2b_request.json` - Copy-paste examples for testing
1126
+
1127
+ **Working Example Results**: The OrderB2B API demonstrates:
1128
+ - ✅ External format mapping (Account → Customer, Name → Product)
1129
+ - ✅ Automatic lookups with error handling (missing customer/product detection)
1130
+ - ✅ Business logic inheritance (unit price copying, amount calculations, balance updates)
1131
+ - ✅ Professional Swagger documentation with YAML examples
1132
+ - ✅ Complete test coverage (success cases and error scenarios)
1133
+
1134
+ ### Customize Models - Add Tables, Attributes
1135
+
1136
+ To add tables / columns to the database (highly impactful - request permission):
1137
+
1138
+ 1. Update `database/models.py` with new models/columns
1139
+ 2. Generate and apply Alembic migration (see database/alembic/readme.md):
1140
+ ```bash
1141
+ cd database
1142
+ alembic revision --autogenerate -m "Description of changes"
1143
+ ```
1144
+ 3. **CRITICAL - Edit the migration file:**
1145
+ - `alembic --autogenerate` detects ALL differences between models.py and database
1146
+ - Open the generated file in `database/alembic/versions/`
1147
+ - **Remove ALL unwanted changes** (ALTER TABLE on existing tables)
1148
+ - **Keep ONLY your intended changes** (e.g., CREATE TABLE for new audit table)
1149
+ - Simplify `downgrade()` function to reverse only your changes
1150
+ 4. Apply the edited migration:
1151
+ ```bash
1152
+ alembic upgrade head
1153
+ ```
1154
+ 5. Offer to update ui/admin/admin.yaml to add the new table or column to the Admin UI.
1155
+
1156
+ **General Migration Notes**:
1157
+ - Stop the server before running migrations to avoid database locking
1158
+ - When adding new models, follow existing patterns in models.py
1159
+ - Models should not contain `__bind_key__`
1160
+ - USER ACTION REQUIRED: Restart server after migrations
1161
+
1162
+ See: https://apilogicserver.github.io/Docs/Database-Changes/#use-alembic-to-update-database-schema-from-model
1163
+
1164
+ If altering `database/models.py`, be sure to follow the patterns shown in the existing models. Note they do not contain a `__bind_key__`.
1165
+
1166
+ ### Addressing `Missing Attributes` during logic loading at project startup
1167
+
1168
+ First, check for misspelling (logic vs `database/models.py`), and repair.
1169
+
1170
+ If there are no obvious misspellings, ask for permission to add attributes; if granted, proceed as above.
1171
+
1172
+ ### Customize Models - Add Derived attributes
1173
+
1174
+ Here is a sample derived attribute, `proper_salary`:
1175
+
1176
+ ```python
1177
+
1178
+ # add derived attribute: https://github.com/thomaxxl/safrs/blob/master/examples/demo_pythonanywhere_com.py
1179
+ @add_method(models.Employee)
1180
+ @jsonapi_attr
1181
+ def __proper_salary__(self): # type: ignore [no-redef]
1182
+ import database.models as models
1183
+ import decimal
1184
+ if isinstance(self, models.Employee):
1185
+ rtn_value = self.Salary
1186
+ if rtn_value is None:
1187
+ rtn_value = decimal.Decimal('0')
1188
+ rtn_value = decimal.Decimal('1.25') * rtn_value
1189
+ self._proper_salary = int(rtn_value)
1190
+ return self._proper_salary
1191
+ else:
1192
+ rtn_value = decimal.Decimal('0')
1193
+ self._proper_salary = int(rtn_value)
1194
+ return self._proper_salary
1195
+
1196
+ @add_method(models.Employee)
1197
+ @__proper_salary__.setter
1198
+ def _proper_salary(self, value): # type: ignore [no-redef]
1199
+ self._proper_salary = value
1200
+ print(f'_proper_salary={self._proper_salary}')
1201
+ pass
1202
+
1203
+ models.Employee.ProperSalary = __proper_salary__
1204
+
1205
+ ```
1206
+
1207
+ When customizing SQLAlchemy models:
1208
+
1209
+ * Don't use direct comparisons with database fields in computed properties
1210
+ * Convert to Python values first using float(), int(), str()
1211
+ * Use property() function instead of @jsonapi_attr for computed properties
1212
+ * Always add error handling for type conversions
1213
+
1214
+ ### Adding events
1215
+ LogicBank rules are the preferred approach to logic, but you will sometimes need to add events. This is done in `logic/declare_logic.py` (important: the function MUST come first):
1216
+
1217
+ ```python
1218
+ # Example: Log email activity after SysEmail is committed
1219
+
1220
+ def sys_email_after_commit(row: models.SysEmail, old_row: models.SysEmail, logic_row: LogicRow):
1221
+ """
1222
+ After SysEmail is committed, log 'email sent'
1223
+ unless the customer has opted out
1224
+ """
1225
+ if not row.customer.email_opt_out:
1226
+ logic_row.log(f"📧 Email sent to {row.customer.name} - Subject: {row.subject}")
1227
+ else:
1228
+ logic_row.log(f"🚫 Email blocked for {row.customer.name} - Customer opted out")
1229
+
1230
+ Rule.commit_row_event(on_class=SysEmail, calling=sys_email_after_commit)
1231
+ ```
1232
+
1233
+ LogicBank event types include:
1234
+ - `Rule.commit_row_event()` - fires after transaction commits
1235
+ - `Rule.after_insert()` - fires after row insert
1236
+ - `Rule.after_update()` - fires after row update
1237
+ - `Rule.after_delete()` - fires after row delete
1238
+
1239
+ All events receive `(row, old_row, logic_row)` parameters and should use `logic_row.log()` for logging.
1240
+
1241
+ ## 📁 Key Directories
1242
+
1243
+ - `logic/` - Business rules (declarative)
1244
+ - `api/` - REST API customization
1245
+ - `security/` - Authentication/authorization
1246
+ - `database/` - Data models and schemas
1247
+ - `ui/admin/` - Admin interface configuration
1248
+ - `ui/app/` - Alternative Angular admin app
1249
+
1250
+ ## 💡 Helpful Context
1251
+
1252
+ - This uses Flask + SQLAlchemy + SAFRS for JSON:API
1253
+ - Admin UI is React-based with automatic CRUD generation
1254
+ - Business logic uses LogicBank (declarative rule engine)
1255
+ - Everything is auto-generated from database introspection
1256
+ - Focus on CUSTOMIZATION, not re-creation
1257
+ - Use CoPilot to assist with logic translation and API generation