Skip to content

Shared map server core: persistent, phase-tagged maps for agents (Phase 1, 0.261.254) - #1638

Open
Paul Lizer (paullizer) wants to merge 3 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-map-server
Open

Paul Lizer (paullizer) wants to merge 3 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-map-server

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a standalone map server (application/map_server) that keeps one persistent map per piece of work, so agents can build a common operating picture over a long conversation instead of redrawing a separate map in every message. It's the first phase of the design in docs/explanation/features/SHARED_MAP_SERVER_DESIGN.md. Nothing in SimpleChat calls it yet; Phase 2 adds the Shared map action, change cards and read-only routes.
  • Phases and history. Every point, path and area records the phase that added it and who added it (agent, run, person and conversation). Each write is one new map version with a change-log entry. Updates keep the earlier state and removals are retracted with a reason, so the map can be shown as of any earlier version or for chosen phases. Duplicates of the same source record are skipped or updated.
  • Access. Every request except /healthz needs an Entra token from a caller holding the MapServer.ActOnBehalf app role (or an allowlisted object ID). Only then is the actor context read (X-Map-Actor: person, user:/group: scope, read or write). A map in another scope answers like a missing one, and read-only access can't write.
  • Storage and runtime. Cosmos DB with one partition per map. Each write is a single transactional batch that replaces the map document only if its ETag is unchanged, so concurrent writers retry instead of skipping or repeating versions. It also includes an Azure Maps tile proxy using the server's own identity (404 without Azure Maps, which the viewer shows as a black background), server-sent change events, /openapi.json with the CDN-backed docs pages turned off, a distroless non-root image and a proof-of-concept deploy script for Azure Container Apps.

Linked issue

None.

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only
  • deployers/version.txt bumped, or not needed because deployers/ was not changed

This takes 0.261.254, after the branch's 0.261.252 and #1637's 0.261.253. Rebased on 2026-10-06 onto paullizer-react-v2-ui at #1647. The map server reports its own version, starting at 0.1.0.

Testing / validation

  • python -m pytest functional_tests/test_map_server_api.py functional_tests/test_map_server_storage_tiles_events.py: 20 passed. Covers caller tokens (wrong audience, issuer, signature and expiry; role versus allowlist), the actor context, scope isolation, limits and safe links, duplicates, phases, revisions and as-of snapshots, the snapshot shape against the keys the V2 inline map renderer reads, filters and paging, the change log, links, concurrent writers getting consecutive versions, store failures never leaking exception text, Cosmos batch and query shapes (ETag condition, parameterized queries), tiles (key and managed identity auth, cache, range checks) and the event stream.
  • The same 20 pass in a clean virtual environment with exactly the pinned application/map_server/requirements.txt, and both files pass under python -O.
  • Local run over HTTP with the in-memory store: create, add, phase, snapshot, a wrong key refused (401) and tiles without Azure Maps (404).
  • scripts/check_broken_access_control.py --full-file and scripts/check_xss_sinks.py --full-file pass on all 12 map server files.
  • functional_tests/test_docs_site_quality.py and functional_tests/test_docs_app_surface_coverage.py: 13 passed.
  • functional_tests/test_logging_tag_standardization.py now scans application/map_server too, and the map server's four tags are documented. The test still fails on this base because of existing camel-case workflow tags (for example [WorkflowResults]), exactly as it does without this change.
  • The deploy script parses cleanly and passes PSScriptAnalyzer apart from Write-Host notes.

Documentation

  • Release notes updated, or not needed (nothing in SimpleChat uses the map server until Phase 2)
  • Feature documentation updated, or not needed (SHARED_MAP_SERVER_DESIGN.md: decisions, data model, API, "Phase 1 as built" with configuration, local run and deployment)
  • Fix documentation updated, or not needed

docs/reference/logging-tags.md lists the new [MAP_SERVER*] tags.

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()) (no Flask routes; the map server is a separate FastAPI service that checks an Entra token on every route but /healthz)
  • Settings sent to non-admin frontends use sanitize_settings_for_user() (no settings sent)
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS (the service serves no browser assets, and FastAPI's CDN-backed /docs and /redoc pages are off)
  • No secrets, keys, connection strings, or local-only artifacts are included

await asyncio.sleep(random.uniform(0.005, 0.02) * (attempt + 1))
continue
return {"map_id": map_id, "version": version, "change_id": change["id"], **plan.result}
LOGGER.warning(f"[MAP_SERVER] A write kept conflicting and gave up (map {map_id}, action {action}).")
if raw_width not in (None, "") and not isinstance(raw_width, bool):
try:
style["line_width"] = max(MIN_LINE_WIDTH, min(MAX_LINE_WIDTH, int(float(raw_width))))
except (TypeError, ValueError):
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 5, 2026
V2 reached 0.261.238 when #1644 merged, so this branch moves one above it.
Sets config.py VERSION to 0.261.239 and moves this branch's own 0.261.238
lines to 0.261.239: the hand-off modules' and tests' Version, Implemented in,
MINIMUM_VERSION and assert_app_version_at_least literals, the two route-test
coverage notes, the run adapter test's hand-off refusal note, the two
hand-off rows in docs/admin/orchestration.md, the feature doc and this
branch's release-notes header. #1644's own 0.261.238 lines (its schema
docstring, its Microsoft 365 section and troubleshooting row in
orchestration.md, its fix docs and its release-notes section) are unchanged.
The open V2 PRs claim 0.261.234 (#1639), 0.261.235 (#1637), 0.261.236
(#1638) and 0.261.246 (#1641), none of them 0.261.239.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 6, 2026
V2 is still at 0.261.233. microsoft#1635, microsoft#1636, microsoft#1637 and microsoft#1638 claim .234 to .236,
so this branch takes .237. Every 0.261.234 reference moves to 0.261.237:
config.py, the release notes header, the feature docs, the chat-controls
reference and the test headers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 6, 2026
Sets config.py VERSION to 0.261.238, one above the versions claimed by the open V2 PRs (microsoft#1636 0.261.234, microsoft#1637 0.261.235, microsoft#1638 0.261.236, 6b-2 next), and moves the hand-off modules' and tests' Version, Implemented in, MINIMUM_VERSION and assert_app_version_at_least literals to it. The off-golden fixture keeps its factual capture note (f1aeef1, 0.261.233).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Proposes a standalone map server for SimpleChat with persistent maps owned by a user or group, phase-tagged features and an append-only change log, a Shared map action with change cards, and a live V2 map panel. Scoped as a proof of concept: SimpleChat is the only client, only agents write, no sharing or deletion rules, and a black background without Azure Maps. Documentation only.
A standalone FastAPI service for persistent, phase-tagged maps that agents build up over a conversation: Entra caller checks with an actor context, scope isolation, versioned writes as ETag-conditioned Cosmos DB batches, revisions for as-of views, a change log, conversation links, an Azure Maps tile proxy, live change events, a container image and a proof-of-concept deploy script. Version 0.261.236.
Filter az output in PowerShell instead of JMESPath functions (az.cmd passes their parentheses through cmd.exe), match role assignments by object ID because a new identity isn't in Entra ID yet, pass an absolute Dockerfile path to az acr build, and wait for new role assignments before creating the container app. Verified by a deploy to a SimpleChat POC environment.
@paullizer Paul Lizer (paullizer) changed the title Shared map server core: persistent, phase-tagged maps for agents (Phase 1, 0.261.236) Shared map server core: persistent, phase-tagged maps for agents (Phase 1, 0.261.254) Oct 6, 2026
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 6, 2026
…esign to 0.261.256

The base moved to 0.261.255, and open PRs microsoft#1654 and microsoft#1638 both hold
0.261.254, so this branch takes the next free number.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants