diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 3e6be37dc..cb7eff6c3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -16,6 +16,9 @@ STYLE Always conform to the coding styles defined in styleguide.md in the root of the repo when generating code. If the styleguide.md is missing, try to check the readme.md in the repo root. If readme.md is missing or contains no useful style information, use the default style of the language. If the default style is not defined, follow best practices, accessibility guidelines, and readability. Use @terminal when answering questions about Git. +FRONTEND ASSETS +Browser runtime JavaScript must always be served from a local SimpleChat static asset. Do not add CDN-hosted JavaScript, dynamic imports, worker scripts, or JavaScript companion assets to app templates, static JavaScript, static CSS, or frontend routes. Vendor pinned local copies under `application/single_app/static/`, reference them with local static paths, and keep CSP aligned with local-only script/style sources. See `.github/instructions/local_browser_assets.instructions.md` for the full rule. + PERSISTENCE You are an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved. @@ -50,4 +53,8 @@ Make code changes only if you have high confidence they can solve the problem. W Confirm the root cause is fixed. Review your solution for logic correctness and robustness. Iterate until you are extremely confident the fix is complete and all tests pass. 7. Final Reflection and Additional Testing -Reflect carefully on the original intent of the user and the problem statement. Think about potential edge cases or scenarios that may not be covered by existing tests. Write additional tests that would need to pass to fully validate the correctness of your solution. Run these new tests and ensure they all pass. Be aware that there are additional hidden tests that must also pass for the solution to be successful. Do not assume the task is complete just because the visible tests pass; continue refining until you are confident the fix is robust and comprehensive. \ No newline at end of file +Reflect carefully on the original intent of the user and the problem statement. Think about potential edge cases or scenarios that may not be covered by existing tests. Write additional tests that would need to pass to fully validate the correctness of your solution. Run these new tests and ensure they all pass. Be aware that there are additional hidden tests that must also pass for the solution to be successful. Do not assume the task is complete just because the visible tests pass; continue refining until you are confident the fix is robust and comprehensive. + +VERSIONING +Application versioning remains in `application/single_app/config.py`. +Deployer and CI/CD versioning lives separately in `deployers/version.txt`; when files under `deployers/` are modified, increment `deployers/version.txt` as part of the same change, defaulting to a patch bump unless a deliberate minor or major compatibility change is intended. \ No newline at end of file diff --git a/.github/instructions/broken-access-control-prevention.instructions.md b/.github/instructions/broken-access-control-prevention.instructions.md index 394e6cd3e..cfb058288 100644 --- a/.github/instructions/broken-access-control-prevention.instructions.md +++ b/.github/instructions/broken-access-control-prevention.instructions.md @@ -11,6 +11,7 @@ applyTo: '**/*.py' Treat all of the following as untrusted authorization inputs unless the code proves otherwise: - `conversation_id`, `message_id`, `document_id`, `file_id`, `approval_id`, `group_id`, and `public_workspace_id` +- `user_id`, Entra object IDs, owner IDs, participant IDs, shared user IDs, and any other identity value supplied by a route path, request body, query string, plugin argument, client-side state, or datastore field - `activeGroupOid` and `activePublicWorkspaceOid` values loaded from user settings - Plugin or tool-call arguments such as `user_id`, `conversation_id`, `group_id`, `public_workspace_id`, `scope_id`, and `scope_type` @@ -19,6 +20,8 @@ Treat all of the following as untrusted authorization inputs unless the code pro Use these patterns by default: - Revalidate personal conversation ownership with `_authorize_personal_conversation_read(...)`, `_authorize_personal_conversation_access(...)`, or an explicit owner check before reading dependent data. +- Revalidate user-profile and user-settings reads with an object-level helper such as `_authorize_user_profile_access(...)`, `_read_authorized_user_profile_document(...)`, or `get_user_settings(...)` instead of reading arbitrary user documents by request-derived `user_id`. +- For cross-user profile display, prove a legitimate app relationship at the read boundary: self, Admin, shared group membership with view allowed, shared document relationship, or shared collaboration conversation participation. - Route `activeGroupOid` writes through `update_active_group_for_user(...)`. - Route `activePublicWorkspaceOid` writes through `update_active_public_workspace_for_user(...)`. - Resolve active group scope through `require_active_group(...)` instead of raw settings reads in backend and plugin code. @@ -33,6 +36,8 @@ Do not add new code that does any of the following without a reviewed exception: - Call `update_user_settings(...)` with a literal `{"activeGroupOid": ...}` payload outside `update_active_group_for_user(...)` - Call `update_user_settings(...)` with a literal `{"activePublicWorkspaceOid": ...}` payload outside `update_active_public_workspace_for_user(...)` - Read `activeGroupOid` or `activePublicWorkspaceOid` directly from raw settings in backend routes or plugins when a shared validator exists +- Call `cosmos_user_settings_container.read_item(...)` from frontend/API routes with a route, query, or body `user_id` unless an object-level user-profile authorization helper has already allowed that exact target. +- Treat `@login_required`, `@user_required`, `@admin_required`, Graph lookup availability, GUID opacity, or frontend-only UI reachability as sufficient authorization for another user's profile, settings, photo, membership, or ownership metadata. - Expose `user_id`, `conversation_id`, `group_id`, `public_workspace_id`, `scope_id`, or `scope_type` in a `@kernel_function` surface without immediately rebinding those values to the authorized request context - Read a personal conversation by request-derived `conversation_id` and continue to message, blob, or feedback work without an explicit ownership boundary @@ -84,20 +89,33 @@ conversation_item = cosmos_conversations_container.read_item( ) ``` +```python +user_doc = cosmos_user_settings_container.read_item( + item=user_id, + partition_key=user_id, +) +``` + ## PR Review Checklist For any Python change that reads or mutates user, group, workspace, conversation, or plugin-scoped data: 1. Identify every caller-controlled id that crosses into a data read or mutation. -2. Revalidate ownership or membership at the sensitive operation boundary, not just at route entry. -3. Use the dedicated active-scope validators instead of raw settings reads and writes. -4. Rebind plugin scope parameters to the authorized request context before storage, blob, or Cosmos access. -5. Add or update a regression test when the change touches an authorization boundary. +2. For every object id, answer: "Why can this caller read or mutate this exact target object?" Do not rely on login, role-only decorators, hidden UI, GUID entropy, or prior lookup flows. +3. Revalidate ownership, membership, or another explicit relationship at the sensitive operation boundary, not just at route entry. +4. For reverse lookups from opaque IDs to identity metadata, verify that the endpoint does not become a user-enumeration or app-membership oracle. +5. Use the dedicated active-scope validators instead of raw settings reads and writes. +6. Rebind plugin scope parameters to the authorized request context before storage, blob, or Cosmos access. +7. Add or update a regression test when the change touches an authorization boundary. ## Workflow Guardrail This repository includes a Development PR check in `.github/workflows/broken-access-control-check.yml` backed by `scripts/check_broken_access_control.py`. +For full-code audits, run the manual GitHub Actions workflow `.github/workflows/broken-access-control-full-scan.yml`. It scans tracked Python files under the selected target paths, uploads a report artifact, and defaults to advisory mode because legacy findings may exist. Set `fail_on_findings=true` only when the current baseline is clean enough for a blocking run. + +For an agent-assisted review, run the workspace prompt `.github/prompts/broken-access-control-audit.prompt.md` and provide the feature area, target paths, or incident class you want reviewed. + If a reviewed exception is unavoidable, add the suppression token below near the specific line and include a justification comment: ```text diff --git a/.github/instructions/local_browser_assets.instructions.md b/.github/instructions/local_browser_assets.instructions.md new file mode 100644 index 000000000..0197930fc --- /dev/null +++ b/.github/instructions/local_browser_assets.instructions.md @@ -0,0 +1,44 @@ +--- +applyTo: '**/*.html, **/*.js, **/*.css, **/*.py' +--- + +# Local Browser Runtime Assets + +## Critical Requirement + +Never load browser runtime JavaScript from the public Internet. If SimpleChat uses a JavaScript library, framework, worker script, module, import map, or plugin runtime in the browser, keep a pinned local copy in the repository and serve it from the SimpleChat app. + +This rule also applies to browser companion assets that are required by JavaScript libraries, including CSS, fonts, source maps, worker files, WebAssembly files, dictionaries, and library-managed fallback downloads. + +## Required Pattern + +- Store third-party browser assets under an appropriate local static path, such as `application/single_app/static/js//` or `application/single_app/static/css//`. +- Reference browser assets with local static paths, preferably through `url_for('static', filename='...')` in templates. +- Pin the library version in the filename, folder name, documentation, or related test when the upstream asset is copied locally. +- Preserve required third-party license or attribution files when vendoring assets. +- Disable library options that auto-download extra browser assets unless those extra assets are also available locally. +- Keep Content Security Policy `script-src` and `style-src` aligned with local assets; do not loosen CSP to allow a CDN for browser runtime code. + +## Disallowed Patterns + +Do not add runtime browser references to: + +- CDN-hosted scripts or modules, such as `cdn.jsdelivr.net`, `unpkg.com`, `cdnjs.cloudflare.com`, `esm.sh`, `skypack.dev`, `code.jquery.com`, or `stackpath.bootstrapcdn.com`. +- Remote CSS for JavaScript-driven widgets when a local copy is expected. +- Library defaults that inject remote ` +{% endif %} \ No newline at end of file diff --git a/application/single_app/templates/_deep_research_info.html b/application/single_app/templates/_deep_research_info.html new file mode 100644 index 000000000..c111393a0 --- /dev/null +++ b/application/single_app/templates/_deep_research_info.html @@ -0,0 +1,175 @@ + + diff --git a/application/single_app/templates/_governance_info.html b/application/single_app/templates/_governance_info.html new file mode 100644 index 000000000..e6d6da40e --- /dev/null +++ b/application/single_app/templates/_governance_info.html @@ -0,0 +1,339 @@ + + + + \ No newline at end of file diff --git a/application/single_app/templates/_multiendpoint_modal.html b/application/single_app/templates/_multiendpoint_modal.html index 3c41dee24..6380cd6be 100644 --- a/application/single_app/templates/_multiendpoint_modal.html +++ b/application/single_app/templates/_multiendpoint_modal.html @@ -4,11 +4,29 @@ - +
Configuration
- +
- +
@@ -83,22 +87,22 @@
Configuration
- +
- Base URL of your API (without trailing slash). + Base URL of your API (without trailing slash).
This will be auto-populated from your OpenAPI spec if available, but you can modify it as needed.
- +
API Information
- +
- + +
+ + +
+
+ - + - + - +
- +
@@ -175,6 +185,11 @@
API Information
+
+ + +
+
Identity @@ -189,426 +204,1619 @@
API Information
- - -
-