Djinious
DjiniousMapAgent GIS

Open data is not a dataset.It is a claim to check.

Geospatial control planeModelOperate

DjiniousMap harvests geospatial data, measures what it actually contains, and refuses to draw it until the coordinates support a reading. What survives that becomes a live map, a spatial analysis, a workflow — or an answer an AI agent gives your team.

DjiniousMap
A dataset detail page showing EPSG:4326 declared, EPSG:2154 inferred at 100% confidence, a warning that the two disagree, a full profile, quality findings, and its points drawn over Provence-Alpes-Côte d’Azur.
A harvested dataset whose publisher declared EPSG:4326 while its coordinates measure as EPSG:2154. Both readings are kept, the disagreement is stated, and the map is drawn from the inferred CRS — the only one supported by evidence.
stores, one tenancy guarantee
2stores, one tenancy guaranteeSurrealDB PERMISSIONS · PostGIS RLS
row-level security, owner included
FORCErow-level security, owner includednosuperuser · nobypassrls
request headers read for identity
0request headers read for identitysession cookie only · no dev stub
CRS inference confidence, in the capture above
100%CRS inference confidence, in the capture abovedeclared 4326 · measured 2154

What it is

A catalogue, a map studio, and an analysis engine that share one tenancy model

Most geospatial stacks are three products stitched together: something that ingests, something that draws, something that computes. Each keeps its own copy of who may see what. DjiniousMap is one control plane, and the isolation is enforced underneath all three.

Harvested catalogue

A harvester pulls public datasets and registers them with their source URL, licence and classification. Registered is not the same as present: nothing is copied into the platform until you materialize it, and the catalogue says plainly which is which.

data.gouv.fr · your own sources

CRS inference

The publisher’s declared coordinate reference system is treated as a claim. The platform measures the coordinates, names the CRS they are actually in, and reports its confidence. When the two disagree, both are kept and the disagreement is shown.

EPSG · declared vs measured

Quality findings

Excess coordinate precision, stale data, invalid or null geometry — each finding explains what was measured, why it matters, and what to do. When there is nothing to judge by, the verdict is Undetermined rather than a guess dressed as a result.

with remediation, and with “undetermined”

Map studio

Compose materialized datasets into layers, style them, filter them, and add category, histogram, formula or time-series widgets that cross-filter the map. A map is a versioned asset, so a view can be published, shared and rolled back.

deck.gl · IGN basemaps

Spatial analysis

Run isochrones, routes, forward and reverse geocoding, and spatial joins against materialized layers. Results land back in the catalogue as datasets of their own, so an analysis output is a first-class input to the next one.

isochrones · routing · geocoding

Workflows and automation

Author a pipeline on a canvas, publish it as a versioned asset, and trigger it on a schedule or on an event — dataset.refreshed, for instance. Runs execute on a leased job queue and stream their progress live.

event and schedule triggers

Inside the product

See it working.

Every capture below is the running product.

01 · 01 · Harvest

Registered is not the same as present

Register a dataset from the public catalogue or from one of your own connections. Registration records where the data lives, who publishes it, how it is licensed and how it is classified — public, internal, restricted or confidential. No features have moved yet.

  • Public harvest from data.gouv.fr, with the publisher’s own identifiers preserved
  • Your own sources through connections, registered the same way
  • Registered but not materialized is a first-class state, shown as such in the catalogue
DjiniousMap
The DjiniousMap dataset catalogue, each row carrying its source, classification and state, with per-row actions for geocoding, reverse geocoding, isochrones and routing on the rows that have been profiled.
The catalogue distinguishes Registered from Profiled. A reference entry carries a source URL and nothing else; a profiled one has had its features copied in and measured, which is what unlocks the spatial actions on the right.

02 · 02 · Profile

The declared CRS is a claim; the inferred CRS is a measurement

Materializing copies the features into the platform and profiles them: feature count, geometry types, spatial index, null and invalid geometry rates, the temporal columns, and the coordinate reference system the numbers are actually in. The profile is what everything downstream trusts — and a dataset cannot be drawn before it is profiled, because drawing it anyway is how a layer ends up in the Gulf of Guinea.

  • The inferred CRS is reported with a confidence, beside the publisher’s declared code
  • A disagreement between them is surfaced, never silently corrected
  • Where no CRS can be inferred, the dataset is refused for mapping and the table preview still works
DjiniousMap
A dataset detail page showing EPSG:4326 declared, EPSG:2154 inferred at 100% confidence, a warning that the two disagree, a full profile, quality findings, and its points drawn over Provence-Alpes-Côte d’Azur.
The publisher declared WGS 84 while the coordinates measure as RGF93 / Lambert-93 at 100% confidence. The platform keeps both values, states the contradiction, and draws the map from the inferred one.

03 · 03 · Compose

A map is a document. Documents have versions.

Bring materialized datasets together as layers on a map: style them, order them, filter them, and add widgets that cross-filter every other layer. The map is a document, versioned like any other asset, so a published view is reproducible and a bad edit is one version away from undone.

  • Category, histogram, formula and time-series widgets, each cross-filtering the map
  • Time replay over any column the profiler identified as temporal
  • IGN and other basemaps, with the layer paint drawn from the product’s own design tokens
  • Only profiled datasets are offered as layers, so a layer cannot be built on coordinates whose projection is unknown
DjiniousMap
The DjiniousMap studio showing Lyon arrondissements as orange polygons and the Rillieux-la-Pape cycle network as blue lines over the Plan IGN basemap, an Arrondissement category widget, and a time replay rail.
Two materialized layers composed over Plan IGN, with a category widget cross-filtering by arrondissement and a time replay rail bound to the layer’s own date column.

04 · Three dimensions

Extrude a layer by a column it already carries

A polygon layer with a numeric attribute can be extruded by it. The obvious case is building height: BD TOPO ships a measured height on every footprint, so setting “Extrude by” to that column turns a plan into a massing model — and because the value is the building’s own, the volume is a reading rather than an illustration.

  • Any numeric column can drive elevation; the exaggeration is explicit and defaults to 1
  • Pitch and bearing are part of the saved document, so a published 3D view opens as it was authored
  • The extruded layer filters and cross-filters like any other — a histogram on height narrows the model
  • Offered only on polygon layers, because there is nothing to extrude on a point or a line
DjiniousMap
The DjiniousMap studio showing BD TOPO Paris buildings extruded into a massing model under a pitched camera, looking across the Seine over Île de la Cité, Notre-Dame, the Quartier Latin and Les Halles, with a height histogram widget.
Every BD TOPO® footprint in view, extruded by its own measured height at exaggeration 1 — 606,667 buildings in the layer. The histogram on the right cross-filters the model by height.

05 · 04 · Act

Run it, publish it, schedule it, share it

Run an analysis, publish a workflow, schedule it, share the result. Work that takes time runs on a leased job queue with heartbeats, so a worker that dies mid-run releases its lease instead of stranding the job — and every mutation lands in an append-only audit log on the way past.

  • Isochrones, routing, forward and reverse geocoding, and spatial analysis over materialized layers
  • Workflows authored on a canvas, published as versioned assets, triggered by schedule or event
  • Public share links and embeddable maps, including a conversational embed
DjiniousMap
The DjiniousMap automations page listing event- and schedule-triggered automations with their target workflow, trigger and last run status.
An automation binds a trigger to a published workflow version. This one fires on dataset.refreshed for the BD TOPO harvest and rebuilds the aerodrome access isochrones.

06 · Watch it work

An agent auditing the catalogue, mirrored live

An external agent is asked which datasets the platform will refuse to draw. It searches the catalogue, reads two profiles, and explains the difference between a dataset with no inferable CRS and one whose publisher simply declared the wrong code. Its conversation appears in the assistant panel as it works.

  • The external agent opens a session and pushes its transcript in; there is no LLM attached on this side
  • It renders with the same blocks a native run produces — reasoning, tool calls with their arguments and results, the answer
  • It is a session like any other: tenant-scoped, in the append-only log, replayable, exportable
DjiniousMap
Recorded against the seeded development stack. The application is real and so is the mirroring — the transcript is pushed through the same endpoint any external agent would use. The agent’s turns are scripted so the recording is reproducible; every figure it quotes is checked against the running stack before the capture starts.

AI & agents

An agent inside the tenancy model, not beside it

The assistant is not a wrapper that reads your screen. It calls the same API you do, as a principal the database recognises, under the same row-level policies — so there is no question of what it can reach, and no second permission model to keep in step with the first.

01

It plans before it acts

Asked for something consequential, the agent proposes a plan and stops. You see the analysis it intends to run and the layers it intends to touch, and it waits. An agent that runs first and reports afterwards is one you have to supervise; one that proposes is one you can direct.

02

Every tool call is visible

The transcript shows each tool call with its arguments and its result as it happens — including the calls that returned an error. A tool that failed and was retried is part of the record, because a trace that only shows the successful path is a summary, not a trace.

03

It answers with the catalogue’s own objects

When the agent talks about a dataset it renders the dataset’s card: the profile, the CRS reading, the findings. You are looking at the platform’s own view of the record, not at the agent’s paraphrase of it.

04

Its reach is a database fact

The agent signs in as a principal like any other. A query it should not be able to answer returns nothing, for the same reason it would for a person: the policy did not produce the rows. There is no agent-specific allowlist to get wrong.

05

An MCP server, with tokens scoped per agent

Agents outside the app — a coding assistant, a scheduled analyst, your own tooling — reach the platform through a Model Context Protocol server, with the same tool surface the in-app assistant uses. Tokens are minted per agent and carry their own scopes, and revoking one leaves every other agent’s session untouched.

06

Conversation mirroring

An external agent’s transcript renders in the app’s own assistant panel, badged and without a composer, because a mirror session has no run to start. The server allocates sequence numbers under a per-session lock, and the event kinds are the same closed set a native run appends.

07

A conversational embed for readers

A published map can be embedded with a chat panel beside it, scoped to that map’s data by the share token. A reader asks a question in words and gets an answer drawn from the layers on the map — without an account, and without reach beyond what the token already made public.

DjiniousMap
The API tokens tab of DjiniousMap settings, listing three minted MCP tokens — a laptop client, a scheduled audit and a read-only notebook — each with its creation date, last-used state and its own Revoke control.
One token per agent, each revocable on its own. The secret is shown once at creation and never again, which is why none appears here.

Capabilities

The whole surface, part by part

DjiniousMap is one Bun API over two databases, with a React client on top: what harvests data, what measures it, what draws it, what computes on it, and what keeps every tenant’s rows out of every other tenant’s queries.

Ingest4 capabilities

Public harvest

A harvester registers datasets from data.gouv.fr, keeping the publisher’s own external identifier, source URL, licence and update frequency. Re-harvesting updates the registration in place rather than creating a duplicate.

Connections

Register your own sources and create datasets from them. A connection carries its credentials and its reachability separately from the datasets that use it, so rotating a secret does not orphan a catalogue entry.

Materialization

Copying a dataset’s features into the platform is an explicit act with its own job. It downloads the source, detects the format, and inserts in batches into a table created for that dataset alone — one table per dataset, never a shared feature store.

Formats

GeoJSON, GeoPackage and the compressed variants the French open-data catalogue actually publishes, including gzipped GeoJSON measured in hundreds of megabytes. Ingest streams rather than buffering, so source size is bounded by disk, not by memory.

Measurement5 capabilities

CRS inference

The coordinates are measured and matched against candidate projections, producing an inferred EPSG code and a confidence. The publisher’s declared code is recorded beside it and never overwritten. When the two disagree, the platform says so and draws from the measured one.

The profile

Feature count, geometry types, spatial index presence, null and invalid geometry rates, temporal columns, declared and inferred SRID, and the WGS 84 bounding box. The bbox is computed in PostGIS because ST_Transform lives there and nowhere else.

Quality findings

Each finding states what was measured, why it matters, and the remediation. Excess coordinate precision quantifies the implied accuracy against survey-grade GNSS; stale data names the column and the threshold; invalid geometry reports a rate rather than a verdict.

Undetermined is a result

When the inputs a finding needs are missing — no declared update frequency, no owner, no date-shaped column — the verdict is Undetermined and the page says which inputs were absent. A guess presented as a measurement would be worse than no answer.

Suitability

A dataset that cannot be placed on a map is flagged as unsuitable for visualization, with the finding that caused it. The table preview keeps working: the data is not unusable, it is unmappable, and the platform distinguishes the two.

Composition5 capabilities

Layers

Materialized datasets become layers with their own style, opacity, order and visibility. Fill, stroke, stroke width and point radius are set per layer, and the paint resolves through the product’s design tokens, so switching brand palette repaints the map along with the chrome.

Filters

Categorical, range and temporal filters per layer, composable and shareable. A filter authored by a widget is tracked back to it, so removing the widget removes the filters it authored — atomically, rather than leaving orphans behind.

Widgets and cross-filtering

Selecting in one widget filters the map and every other widget, which is what makes a multi-layer map explorable rather than merely legible.

Time replay

Any column the profiler identified as temporal can drive a timeline: scrub it, or play it, and the map redraws over the period. The rail appears only when such a column exists, so it never implies a time dimension the data does not have.

Versioned assets

A map is an asset with immutable published versions, a slug and a current version pointer — the same model as a workflow. Publishing freezes a document and hashes its body, so a shared view is exactly the one that was shared.

Computation5 capabilities

Spatial analysis

Run analyses over materialized layers and land the result back in the catalogue as a dataset of its own, profiled like any other. An output is therefore a first-class input, and the lineage is a catalogue relationship rather than a filename convention.

Isochrones

Travel-time polygons from a point or from every feature in a layer, through a pluggable routing provider. The result is a dataset, so it can be styled, filtered and joined like anything else.

Routing

Point-to-point routes with the same provider abstraction, returning a geometry the studio can draw.

Geocoding, both directions

Forward geocoding turns an address column into points; reverse geocoding turns points into addresses. Both run as jobs over a whole dataset rather than one row at a time.

The job queue

Anything that takes time runs on a leased queue with heartbeats. A worker that dies mid-run stops heartbeating and its lease expires, so the job is picked up again instead of being stranded in a running state forever.

Orchestration3 capabilities

Workflow canvas

Author a pipeline as a graph, configure each node, and publish it as a versioned asset. A run streams its progress live, and the stream is durable: reconnecting replays the run from its event log rather than losing what happened while you were away.

Triggers

Automations bind a trigger to a published workflow version. Schedule triggers fire on a cadence; event triggers fire on platform events such as dataset.refreshed, so a rebuild follows a harvest without anybody watching for it.

Last-run status

Each automation carries the outcome of its most recent run, so a pipeline that has been failing quietly for a week is visible on the list page rather than only in a log.

Distribution3 capabilities

Public share links

Publish a map behind a share token for readers with no account. The token scopes what is readable; it is not a bypass of the tenancy model but a principal within it.

Embeds

The same viewer runs in embed mode for putting a live map inside another page — including a conversational embed, where the reader asks questions of the map rather than operating its controls.

Provider Interface v1

Exposes the platform as a service to sibling Djinious applications: scoped service tokens, a versioned operation surface under /api/provider/v1, and /ready, /version and /metrics for the operator.

Trust

Isolation you can check, not isolation you are promised

Multi-tenancy is usually a review problem: every new query is one missed WHERE clause away from a leak. DjiniousMap moves the boundary into the two databases, where a wrong query returns nothing rather than returning somebody else’s rows.

SurrealDB — permissions per verb

Every table is SCHEMAFULL and carries a PERMISSIONS clause for each verb, evaluated against the record the connection signed in as. A denied read returns nothing. A denied write returns nothing either — which is why every write checks that a row came back rather than assuming it landed.

SCHEMAFULL · PERMISSIONS

PostgreSQL — row-level security with FORCE

Feature tables are governed by row-level security declared FORCE, so the policies apply to the owning role as well. That role is created nosuperuser and nobypassrls: there is no principal in the database that can read past a policy, including the one that created the table.

nosuperuser · nobypassrls

The organization is set before the first statement

Every request opens its transaction through a helper that sets the organization before any statement runs; the policies read that setting. A request that resolved no organization cannot open a transaction at all, so “forgot to scope it” is not a reachable state.

SET LOCAL, per transaction

Materialization is guarded by the database too

The function that creates a dataset’s feature table first checks the dataset exists — a check that runs under the caller’s own row-level security. A tenant asking to materialize another tenant’s dataset sees no row and is refused by the database, not by a handler.

security definer, caller’s RLS

The suite derives its expectations from the grants

The cross-tenant test suite walks both stores and builds its expectations from the grants and policies it finds, rather than from a list somebody maintains. A table added without a policy fails the walk instead of passing because nobody remembered to add a case.

isolation tests

A session cookie, and nothing else

Passwords are Argon2id, verified in the database. The session is a 256-bit random token in an HttpOnly cookie, of which only the SHA-256 hash is stored. Request headers are never consulted for identity, and there is no stub and no override. Login credentials federate to the shared Djinious core.

Argon2id · HttpOnly · SHA-256

An append-only audit log, with required retention

Every mutation lands in an append-only audit log on the mutation path. A scheduled maintenance sweep handles audit retention and session expiry, and a reconcile command enumerates both stores and exits non-zero when the projected rows disagree.

audit · reconcile

In the digital thread

What it takes in. What it hands on.

DjiniousMap does its part of the engineering loop and passes its evidence along — and it works just as well on its own.

On its own

DjiniousMap is a complete geospatial platform on its own: harvest open data or your own sources, profile it honestly, compose it into versioned maps, run isochrones, routing and geocoding, and automate the pipeline — with tenancy enforced by the database rather than by application code.

Book a demo

See it on your problem.

Bring the dataset you have argued about. Ninety minutes against your own data, not ours: we will profile it in front of you and read the result as it comes — including the parts where the platform declines to draw it, and why.

  1. Register a dataset you bring — from a URL, or from one of your own sources through a connection
  2. Materialize it live and read the profile out loud: CRS, geometry, index, null and invalid rates
  3. Go through its quality findings, including the ones that come back Undetermined and why
  4. Compose it into a map with a second layer, filter it, and cross-filter with a widget
  5. Run one analysis on it — an isochrone or a spatial join — and watch the result land back in the catalogue
  6. Ask the assistant something we did not prepare for, with the tool trace visible