根因:develop 从不 load_skill module-development-spec,是因为 description 只写「是什么」 (英文的 Standardized workflow...),没写「什么场景必须加载我、不加载会怎样、什么场景别用我」。 目录层只注入 name+description,description 是 agent 决定是否 load_skill 的唯一触发依据, 写不清触发条件 → agent 不加载 → 规范静默失效。 改为:每个角色技能 + 关键规范技能的 description 都写清 ① 触发场景(开发模块/应用脚手架/部署/测试/审查时必读)② 该加载哪个规范 ③ 不加载的后果(模块带 app.py 等)。
14 KiB
| name | version | description | trigger_conditions | |||
|---|---|---|---|---|---|---|
| web-application-spec | 1.0.0 | 开发「应用脚手架」时必读——应用是唯一部署单元(一个入口 app/{应用名}.py + 一个端口),init() 里定义 get_module_dbname 挂 ServerEnv 再逐个 load_{模块}() 挂载业务模块,含 conf/config.json、build.sh 一键部署。开发「业务模块」(Python 包)时不要用本技能,改用 module-development-spec。 |
|
Web Application Specification
Overview
This specification defines the standard architecture for web applications built using:
- Frontend: bricks framework
- Backend: ahserver application framework
- Foundation: apppublic and sqlor modules
- Optional Modules: appbase, rbac, and other developed modules
All web applications must follow this exact structure and configuration pattern.
Required Dependencies
Core Dependencies (Mandatory)
pip install git+https://git.opencomputing.cn/yumoqing/apppublic
pip install git+https://git.opencomputing.cn/yumoqing/sqlor
pip install git+https://git.opencomputing.cn/yumoqing/ahserver
Database Web Application Dependencies (If using database)
pip install git+https://git.opencomputing.cn/yumoqing/appbase
pip install git+https://git.opencomputing.cn/yumoqing/rbac
Application Directory Structure
${appname}/
├── app/
│ └── ${appname}.py # Main application entry point
├── conf/
│ └── config.json # Application configuration
├── files/ # File storage directory
├── logs/ # Log files directory
├── wwwroot/
│ ├── imgs/ # SVG and image files
│ └── bricks/ # Bricks framework distribution
├── build.sh # Initialization and deployment script
└── .env # Environment variables
File Specifications
app/${appname}.py (Main Application)
from ahserver.webapp import webapp
from ahserver.serverenv import ServerEnv
import bricks_for_python # registers bui processor
from bricks_for_python.init import load_pybricks # registers UiWindow etc.
from appbase.init import load_appbase
from rbac.init import load_rbac
def get_module_dbname(m):
# 返回模块 m 对应的数据库名。库名由应用统一决定,模块禁止硬编码 DBNAME(见 module-development-spec)。
# 实现方式:应用级「模块名 → 库名」映射,从 appbase params 表 / conf/config.json 读,或直接映射表。
# 例:单库应用所有模块返回同一主库名;多库应用按模块返回各自库名。勿写死 'dbname'/'hrs6'。
return module_dbname_map(m)
def password_encode(s):
if s is None:
return ''
from ahserver.globalEnv import password_encode as _orig
return _orig(s)
def init():
env = ServerEnv() # ← MUST be before load_rbac
env.get_module_dbname = get_module_dbname
env.password_encode = password_encode
load_appbase()
load_rbac()
load_pybricks()
# ── 业务模块导入(关键:一个应用一个入口一个端口,所有模块挂在这里)──
from organization.init import load_organization
from payroll.init import load_payroll
load_organization()
load_payroll()
if __name__ == '__main__':
webapp(init)
应用对模块的完整导入(关键,build.sh 一键部署必须覆盖):一个应用 = 一个入口(
app/${appname}.py)= 一个端口。业务模块(organization/payroll/recruitment/...)是 Python 包,不是独立服务。应用通过 build.sh 把各模块完整集成进来,步骤如下:
- 代码导入(git pull):模块从 git clone 到
pkgs/{模块名}/(基础包 apppublic/sqlor/ahserver/rbac/xls2ddl/appbase/bricks 同)。禁止手动复制源码。- 依赖安装(pip install):
pip install -e pkgs/{模块名}(或pip install)安装所有模块;无 pyproject.toml 的用 PYTHONPATH。- 前端链接(wwwroot 软链):
ln -sf ../pkgs/{模块名}/wwwroot wwwroot/{模块名}(软链接非 cp,保持同步)。- i18n 导入:merge_i18n.py 合并各模块
i18n/{zh,en}/msg.txt→wwwroot/i18n/{lang}/i18n.json(i18n_getmsgs.dspy 供 bricks.js 读取)。- 建表(DDL):json2ddl 从模块
models/*.json生成mysql.ddl.sql,执行建表。- CRUD 生成:xls2ui 从模块
json/*.json生成 CRUD(.dspy + .ui)。- 初始化数据:
python scripts/init_data.py导入模块init/data.json(appcodes 等种子数据)。- 运行挂载(load_{module}()):应用
app/{appname}.py的init()里逐个load_{module}()(见上)。不要给每个模块单独建
app.py、单独占端口、单独起服务——模块不是独立部署单元,应用才是。以上 8 步是应用一键部署正确执行的完整清单,缺一不可。
conf/config.json (Configuration)
Must include the following sections:
password_key: System encryption keylogger: Logging configuration with name, level, and file pathfilesroot: File storage root path using$[workdir]$placeholderdatabases: Database connection configurations with driver and kwargswebsite: Web server configuration including paths, processors, session settings
Key Configuration Patterns:
- Use
$[workdir]$placeholder for work directory references - Database names in
databasessection must matchget_module_name()return values - Critical: processors must include
.tmpl→tmpl. The BricksUIProcessor (handler for.uifiles) internally loads/bricks/header.tmpland other templates. Without[".tmpl", "tmpl"], the app returns 500'NoneType' has no attribute 'be_call'on/and/index.ui:"processors": [ [".tmpl", "tmpl"], [".ui", "bui"], [".dspy", "dspy"] ] - Website processors must include
.ui→buiand.dspy→dspymappings - Website indexes: Must include
"index.ui"for bricks-based apps. Without it, visiting/or/module/returns 500 "invalid path" because ahserver cannot resolve directory URLs:"indexes": ["index.ui", "index.html"] - WebSocket support: Must include
[".wss", "ws"]in processors list, otherwise.wssfiles are served as static files and WebSocket connections fail. Nginx/wss/block strips the prefix viaproxy_pass, so the backend receives the path without/wss(e.g.,/module/file.wss).
WebSocket Configuration Details
When adding WebSocket (.wss) endpoints to a module:
-
Backend config.json: Add
[".wss", "ws"]towebsite.processors:"processors": [ [".wss", "ws"], [".ws", "ws"], [".ui", "bui"], [".dspy", "dspy"] ] -
Nginx: The
/wss/location block handles WebSocket upgrade and strips the prefix:location /wss/ { proxy_pass http://localhost:9180/; # strips /wss prefix proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } -
Frontend: Connect to
/wss/module/file.wss(with/wssprefix):var url = protocol + '//' + host + '/wss/module/file.wss'; var ws = new WebSocket(url); // browser auto-sends cookie -
RBAC permissions: Register paths without
/wssprefix (nginx strips it):python set_role_perm.py "logined" "/module/file.wss" -
Common pitfall: If ahserver logs
handle as a normal filefor a.wssrequest, the[".wss","ws"]processor mapping is missing fromconfig.json. ahserver only recognizes extensions explicitly listed inprocessors.
build.sh (Deployment Script)
The build script must perform these operations in order:
A) Module Dependencies Setup
- Install xls2ddl tool: After creating virtual environment, install xls2ddl first:
pip install xls2ddl - Module Installation: Clone and pip install all required modules
- Database DDL Generation: For modules with
models/directory:- If models contain
.xlsxfiles:cd models/ xls2ddl mysql . > mysql.ddl.sql mysql -h db -u[user] -p[password] [dbname] < mysql.ddl.sql - If models contain
.jsonfiles:cd models/ json2ddl mysql . > mysql.ddl.sql mysql -h db -u[user] -p[password] [dbname] < mysql.ddl.sql
- If models contain
- Initial Data Import: For modules with
data/directory:dbloader $cdir [dbname] data.xlsx - CRUD Generation: For modules with
json/directory:cd json/ xls2ui -m ../models -o ../wwwroot ${modulename} *.json - wwwroot Symlinking: Create symbolic links for each module:
ln -s $cdir/pkgs/$m/wwwroot $cdir/wwwroot/$m
B) Bricks Framework Setup
- Execute bricks build.sh and symlink dist directory:
ln -s $cdir/pkgs/bricks/dist $cdir/wwwroot/bricks
C) System Service Configuration
- Create systemd service file with proper user/group context
- Generate start.sh and stop.sh scripts with environment loading
- Enable and start the service on system boot
D) Cron Job Management
- Add application-specific cron jobs without duplication
.env (Environment Variables)
- Export all runtime environment variables required by the application
- Include database credentials, API keys, and system paths
Build Script Requirements
Directory Creation
- Create
pkgs/directory for module clones - Create
logs/directory for application logging
Module Processing Order
- Install foundation modules (apppublic, sqlor, ahserver, bricks)
- Clone and process database modules (appbase, rbac):
- Clone from Git repositories to pkgs/ directory
- Install via pip
- Generate DDL from models/ directory (.xlsx or .json files)
- Generate CRUD UI from json/ directory using xls2ui
- Install business modules (accounting, pricing, contract_management, etc.) following the same pattern as database modules
Database Operations
- Process all modules that have
models/,json/, ordata/directories (including appbase and rbac) - Use proper error handling for database operations
- Maintain database isolation per module when configured
Symbolic Links
- All module wwwroot directories must be symlinked to application wwwroot
- Bricks dist directory must be symlinked to wwwroot/bricks
Service Management
- Create proper systemd service with logging redirection
- Implement graceful start/stop scripts
- Set appropriate file permissions (chmod +x for scripts)
Bricks UI Development Pitfalls
See references/ragserver-pitfalls.md for complete debugging recipes.
See references/sage-module-pitfalls.md for SQL column names, params_kw=None, deployment, and error investigation rules.
- Widget
idat top level (NOT inoptions) - DOM order for
app.<id>resolution .tmplprocessor required in configbricks_for_pythonimport +load_pybricks()call- DataViewer response format (
{status, data:{rows,total}}) - Menu widget target pattern
- Float model fields needing
length+dec
Widget id at Top Level (Not in options)
// CORRECT
{"widgettype":"VBox","id":"main_content","options":{"css":"filler"}}
// WRONG — id inside options is ignored
{"widgettype":"VBox","options":{"id":"main_content","css":"filler"}}
DOM Order Affects app.<id> Resolution
Put the content area BEFORE the sidebar in subwidgets. Bricks initializes widgets left-to-right.
Configuration Best Practices
Security
- Store sensitive data (passwords, keys) in encrypted form in config.json
- Use environment variables for runtime secrets via .env file
- Implement proper file permissions for logs and files directories
Performance
- Configure appropriate client_max_size for file uploads
- Set optimal session timeout values (session_max_time, session_issue_time)
- Use Redis for session storage in production
Maintainability
- Use consistent naming patterns across all configuration sections
- Document custom processor mappings in website.processors
- Maintain clear separation between development and production configurations
Verification Checklist
.tmpl→tmplprocessor inwebsite.processors(required for bricks UI, or/returns 500)bricks_for_pythonimported andload_pybricks()called ininit()ServerEnvinitialized BEFOREload_rbac()/load_appbase()- Website
indexesconfig includes"index.ui"(required for directory URL resolution) session_max_timeandsession_issue_timein config for Redis session persistence (restart won't lose login)- All required dependencies are installed from correct Git repositories
- Application directory structure matches specification exactly
- Main application file includes proper module loading pattern
- Configuration file uses correct placeholders and structure
- Build script handles all module types (foundation, database, business)
- Database DDL generation works for all modules with models/
- CRUD generation executes for all modules with json/
- Initial data loads correctly for modules with data/
- All wwwroot symlinks are created properly
- Bricks framework is built and linked correctly
- System service starts and stops gracefully
- Environment variables are loaded from .env file
- Application runs with proper logging and error handling