Repository navigation
RFC: IND AS XBRL support via shared xbrl engine + ind_as adapter (upload → graph v1) #60
Description
Summary
This RFC proposes adding support for Indian IND AS XBRL filings in RoboSystems so they can be ingested and queried similarly to SEC XBRL, without extending the SEC EDGAR adapter into a multi-jurisdiction catch-all. The approach is a shared XBRL engine (adapters/xbrl/) plus a separate IND AS adapter (adapters/ind_as/), with a minimal v1: upload filings (S3/local) → Arelle-based processing → queryable graph. Automated India portal crawling, a shared India repository, MCP, and full SEC-feature parity are explicitly out of scope for v1.
Motivation: Problem
Today RoboSystems’ XBRL path is centered on SEC EDGAR + US filing/taxonomy assumptions (adapters/sec/). Indian companies file under the IND AS taxonomy with different packaging and distribution constraints. Those filings cannot currently enter the same parse → graph → query path.
Extending adapters/sec/ to also mean “India” would couple two jurisdictions, data sources, and operational models (EDGAR rate limits, EFM, SEC shared-repo ops, etc.) and works against clear module boundaries.
An external spike (Arelle successfully loading IND AS taxonomy-based reports) suggests the parse side is feasible; what we need is an agreed in-repo architecture before implementation PRs.
Motivation: Why Now?
- Demand for querying non-US XBRL (IND AS) is a natural extension of the platform’s financial graph story.
- A working Arelle + IND AS spike exists outside the repo, so design discussion can be grounded in something real.
- Upstream SEC has become more SEC-specific (FactSet/report lifecycle, shared-master ops, etc.), which makes “bolt India onto
sec/” a worse default than extracting a thin shared XBRL layer. - Aligning on boundaries now avoids a large, hard-to-review contribution and rework later.
Proposed Design: Overview
Principles
- Separation of concerns: SEC stays the SEC product; IND AS is its own adapter; shared XBRL mechanics live in a neutral module.
- Arelle for instance/DTS truth; a thin curated (or later generated) semantic profile for product-level canonical concepts — not hand-maintaining the full taxonomy as Python classes.
- Minimal vertical slice for v1 that is queryable and extensible; defer product/ops surface area.
High-level layout
adapters/xbrl/ # shared engine: Arelle load, normalize facts/structures
adapters/ind_as/ # India-specific: taxonomy packages, upload ingest, wiring
adapters/sec/ # remains EDGAR/SEC; may gradually call into xbrl/ later
v1 flow
- Operator/user places an IND AS filing package in S3 or local path
ind_asadapter invokesxbrl(Arelle + taxonomy cache/packages)- Emit a stable intermediate representation (subset OK) aligned where practical with existing SEC/reporting graph concepts (facts, elements, contexts, report linkage)
- Materialize into a normal user/demo graph
- Query via existing API/Cypher (success = basic facts / statement structure retrievable)
Explicit non-goals for v1
- India government/exchange bot crawling (sites often restrict automated download; APIs unclear)
- Shared repository for India (manifest, billing, platform-wide corpus like SEC)
- MCP / agent tooling (easy to add later once the graph exists)
- Full parity with SEC (narratives, iXBRL item extraction, corpus knowledge artifacts, incremental shared-master parking, ticker auto-resolve, full enrichment)
Proposed Design: Detailed Design
Architecture
-
adapters/xbrl/- Taxonomy-agnostic Arelle session/load helpers (instance + DTS / taxonomy packages; offline cache)
- Normalization: facts, contexts, units, elements, basic presentation/structure → intermediate tables/parquet (or documented subset of current SEC processor outputs)
- No EDGAR, no EFM-only assumptions in the core path
-
adapters/ind_as/- IND AS taxonomy package/bundle management
- Ingest entrypoint: S3 URI or local path → process one filing (batch later)
- Thin taxonomy semantic profile (optional in earliest PR): map a small set of concepts to canonical tags if needed for v1 queries; prefer deriving structure from Arelle first
-
adapters/sec/- Unchanged behavior initially
- Optional follow-up: migrate shared pieces into
xbrl/behind SEC-compatible wrappers (incremental, no big-bang rewrite in the first IND AS PR)
Data model
- Prefer reusing existing reporting/graph shapes (e.g. Report / Fact / Element / related edges, FactSet only if low-cost) so query patterns don’t permanently fork.
- v1 may populate a subset of fields; document gaps vs SEC.
- Do not require corpus-level knowledge artifacts for v1.
Ingest & runtime
- Source: S3/local upload only in v1.
- Target: private/user or demo graph (not a new shared
indrepository). - Orchestration: smallest useful surface — CLI/
justrecipe and/or a single Dagster job later; full nightly pipeline not required for the RFC approval bar.
APIs / product surface
- v1: existing graph query APIs / Cypher.
- MCP: Phase 1.5+ (optional), after data is queryable.
Extension points (foundation)
| Hook | v1 | Later |
|---|---|---|
| Filing source | S3/local | Approved bulk/API source if available |
| Taxonomy profile | IND AS packages + thin optional map | Generated profiles, richer canonical concepts |
| Shared repository | — | Manifest + billing + hosted corpus (SEC-like) |
| Enrichment / MCP | — | Semantic enricher parity, MCP tools |
Implementation approach for first PRs
- RFC approval / direction from maintainers
- Small foundational PR(s): introduce
xbrlskeleton and/or extract one SEC-safe shared helper with no behavior change - Spike PR or follow-up: one real IND AS package → intermediate shape → graph → documented example queries
- Grow enrichment, automation, shared-repo only after the slice works
Alternatives Considered
| Alternative | Pros | Cons |
|---|---|---|
A. Extend adapters/sec/ for IND AS |
Faster short-term if we only copy processors | Couples jurisdictions; fights SOLID; SEC ops/assumptions leak into India |
B. Shared adapters/xbrl/ + adapters/ind_as/ (this RFC) |
Clear boundaries; reusable for future taxonomies; incremental extraction | Slightly more upfront structure; needs care not to over-abstract |
| C. IND AS-only adapter with duplicated Arelle/processing | Isolated; no SEC touch | Duplication; harder to keep graph contracts aligned |
| D. v1 as shared India repository like SEC | Product parity narrative | Needs hosting, legal/source strategy, billing/manifest, crawler or bulk feed — too large for first contribution |
Why this approach: B gives a solid, extensible foundation with the smallest honest v1 (upload → graph → query), while leaving shared-repo and MCP as deliberate later phases.
Implementation: Phases
- Phase 0 — Alignment: This RFC; confirm package layout and non-goals.
- Phase 1 — Foundation:
xbrlmodule boundaries; optional no-behavior-change extraction from SEC; IND AS taxonomy cache/packages loadable via Arelle. - Phase 2 — Vertical slice: S3/local ingest → process → materialize → example Cypher/API queries on a demo/user graph.
- Phase 3 — Harden: Better error handling, tests with redistributable fixtures, docs/
justrecipe. - Phase 4+ (optional): Thin semantic profile; MCP; shared repository if product decides to host an India corpus; any legitimate automated source.
Implementation: Dependencies
- Arelle (already used by SEC)
- IND AS taxonomy packages (versioning/cache strategy)
- Sample IND AS filings suitable for tests (licensing/redistribution must be respected; synthetic or clearly allowed fixtures preferred in-repo)
- Existing graph materialization / query stack
- Maintainer guidance on how aggressively to share code with
sec/in Phase 1 vs duplicate temporarily
Risks & Mitigations
| Risk | Mitigation |
|---|---|
Over-abstraction in xbrl/ before second taxonomy is real |
Keep xbrl/ thin; only share what IND AS + SEC both need; extract incrementally |
| IND AS instance/DTS differences break SEC-shaped processors | Document schema deltas; allow subset output in v1; spike early with real filings |
| Taxonomy / filing redistribution constraints | Don’t commit proprietary filings; use S3 for real data; fixtures only if permitted |
| Scope creep toward SEC parity or shared repo | Hard non-goals in RFC; success = queryable vertical slice |
| India source automation expectations | State upload-only; crawler blocked until lawful API/bulk channel |
Open Questions
- Are maintainers aligned on
adapters/xbrl/+adapters/ind_as/, vs a thinner “IND AS-only first, extractxbrl/later”? - For v1 graph shape: strict subset of current SEC reporting nodes/edges, vs allow a slightly India-specific schema with a mapping document?
- Preferred v1 entrypoint:
just/CLI only, or also a single Dagster job? - Any existing plans for non-US XBRL / IFRS that this should align with?
- Guidance on taxonomy package bundling (similar to SEC’s Arelle schema bundles) vs download-at-runtime with cache?
References
robosystems/adapters/README.md— shared repository vs private adapter patternrobosystems/adapters/sec/README.md— current XBRL → graph pipeline.github/CONTRIBUTING.md— Feature → RFC → Spec workflow- External spike: local Arelle loading of IND AS taxonomy-based reports (outside this repo)
Activity
MHa55anY commentedon Aug 10, 2026
Note for maintainers: Please set the issue type to RFC if possible —
ghcould not set issue type with read-only permission on this repo (UpdateIssueIssueType). Labeling also requires write access; feel free to addarea:adapters.Also closed accidental duplicate: RoboFinSystems/robosystems#1133.
jfrench9 commentedon Aug 10, 2026
Thanks for this — it's a genuinely well-researched RFC, and the fact that you read the code before proposing shows. Setting the type to
RFCand addingarea:adapters.Where you're right
Your core diagnosis holds up.
adapters/sec/processors/xbrl_graph.pyis ~2,200 lines that importSECClient/SEC_BASE_URL, takesec_filer/sec_reportkwargs, normalize CIK, and minthttp://www.sec.gov/CIK#{cik}as the canonical entity URI. Alternative A (extendsec/) would drag EDGAR assumptions into a second jurisdiction, and we agree it's the wrong default. Non-goals are scoped the way we'd want them — no crawling, no shared repository, no MCP in v1.Two corrections and one question that we think changes the shape of the work.
1. The taxonomy-neutral Arelle layer already exists — one level up from
adapters/robosystems/arelle/is already there and already deliberately taxonomy-neutral. Its entry points areextract_taxonomy(model_xbrl) -> rdflib.Graphandserialize_jsonld(graph, standard, version), and it feedsrobosystems/taxonomy/(discovery.py,loader.py,pins.py,writer.py) which seeds theframeworks/library.It lives outside
adapters/on purpose. Perrobosystems/adapters/README.md, an adapter is an external service integration — a client plus transformation, optionally with a shared-repository manifest. A taxonomy-neutral XBRL engine isn't that; it's platform-scoped machinery. So we'd rather not createadapters/xbrl/: it would put neutral code in the layer reserved for service integrations, and split the neutral Arelle surface across two homes.The extraction candidate you're looking for is real, though — it's just a different file.
adapters/sec/client/arelle.py(ArelleClient, ~700 lines) is cache directory selection, bundled-schema population, offline mode, and controller lifecycle. Almost all of that is jurisdiction-neutral; only the EFM validation configuration is SEC-specific. Hoisting that intorobosystems/arelle/behind a SEC-compatible wrapper is exactly the kind of no-behavior-change foundational PR your Phase 1 describes, and we'd take it on its own merits.So:
robosystems/arelle/grows an instance-side companion to its existing taxonomy-side extractor;adapters/ind_as/(or equivalent) stays thin. Same separation of concerns you argued for, one layer up.2. There are two destinations for a non-US taxonomy here, and the RFC only addresses one
This is the substantive question, and it's your open question RoboFinSystems/robosystems#2 and RoboFinSystems/robosystems#4 combined.
The corpus path — what SEC does. Filings → Arelle → intermediate tables → a graph of raw facts in the source vocabulary, served as a platform-managed public repository. This is the path your v1 flow describes.
The framework path — how a reporting taxonomy becomes something tenants actually report under. A framework is a versioned bundle in
frameworks/pinning(package, version)and(bridge, version)tuples, loaded viarobosystems/taxonomy/, with per-tenant machinery inrobosystems/operations/taxonomy_block/(reporting_standard.py,reporting_extension.py,chart_of_accounts.py). The data model is already built for jurisdictional variants:Taxonomy.extension_typeaccepts'jurisdiction'(robosystems/models/extensions/taxonomy.py), andElement.sourcealready accepts'ifrs'(robosystems/models/extensions/element.py). Bridges map an external vocabulary into our canonical reporting taxonomy so a report can render in both.Your v1 target — "materialize into a normal user/demo graph" — sits between these. That's the ambiguity we'd want resolved before any code, because the two have almost nothing in common downstream:
frameworks/ind-as/bundle plus a bridge, with far less new Python than the RFC anticipates. It would also be a materially smaller and more reviewable first contribution.Which one are you after? The answer changes Phase 2 entirely.
To your question about existing non-US plans: yes, IFRS-adjacent frameworks are a direction we expect to go, and the mechanism we expect to use is the framework/bridge library rather than a per-jurisdiction ingestion adapter. That's why we'd like to pin down which path you mean before locking a package layout.
Answers to your other open questions
Taxonomy bundling (#5). Follow the SEC precedent: bundle, don't download at runtime.
adapters/sec/arelle/bundles/holds versioned tarballs (arelle-schemas-*.tar.gz,edgar-plugin-*.tar.gz) thatArelleClientunpacks into Arelle's cache, with offline mode on. Runtime taxonomy fetches are the thing that makes ingestion flaky and slow, and we don't want a second source of that.v1 entrypoint (#3). A
justrecipe over a CLI entrypoint is enough to start. Dagster only once there's a repeating pipeline worth scheduling — a one-shot ingest doesn't need it.Graph shape (#2). Deferred to the corpus-vs-framework answer above. If it's the corpus path, prefer a documented subset of the existing reporting nodes/edges over a parallel India-specific schema — a fork in query shape is the expensive kind of divergence.
Suggested next step
Rather than the
xbrlskeleton PR, we'd start with:ArelleClientfromadapters/sec/client/arelle.pyintorobosystems/arelle/, SEC calling through a wrapper, existing tests green. That stands alone, is easy to review, and is useful regardless of what happens with IND AS.On fixtures — agreed and appreciated that you raised it. Don't commit filings whose redistribution isn't clearly permitted; synthetic instances against the real taxonomy are fine for tests.
Thanks again for taking the time to write this up properly rather than opening a large PR cold. Happy to keep iterating here.
MHa55anY commentedon Aug 12, 2026
Thanks for the thoughtful reply — this cleared up a lot for me.
On corpus vs framework: my long-term goal is the corpus path (SEC-style). I want Indian XBRL filings ingested and queryable so people can explore them easily, and eventually use MCP/AI to pull insights from the data — comparing companies, spotting trends, asking questions over filed facts. That's "understand what was filed," not "companies report through RoboSystems" as a first step.
I get now that the framework path is the other side of the coin — IND AS as a reporting standard inside the product (
frameworks/ind-as/, bridges, tenant reporting). That's complementary and lines up with the IFRS direction you mentioned; I'd treat it as a follow-on rather than what I'm aiming for in v1.On layering: fully on board with skipping
adapters/xbrl/. Putting shared machinery inrobosystems/arelle/and keeping something likeadapters/ind_as/thin makes sense. HoistingArelleClientintorobosystems/arelle/with SEC calling through a wrapper sounds like the right first move.For v1, I'm still aligned with what we scoped before, with your notes folded in: S3/local upload only, bundled taxonomies (no runtime fetch),
just/CLI to start, and reusing existing graph shapes where we can instead of inventing a parallel India schema. Still out of scope for v1: shared repo, MCP, crawling, full SEC parity.Sequencing — if this works for you:
ArelleClient, no behavior change, SEC wrapper, tests greenOn fixtures: won't commit filings unless redistribution is clearly OK; synthetic instances against the real taxonomy are fine for tests.
If that ordering looks good, I'll start on the Arelle hoist — unless you'd rather framework content land first for sequencing reasons.
jfrench9 commentedon Sep 14, 2026
Moving this to
xbrlkit— and with an update that makes the RFC a good deal smaller.What changed since August
The shared XBRL engine we discussed got extracted, but it went further than either of us planned in this thread: not into
robosystems/arelle/, but out of the platform repo entirely, into xbrlkit (also on PyPI). RoboSystems now depends on it like any other library.Concretely, on the SEC side of the platform:
adapters/sec/client/arelle.py— the ~700-lineArelleClientyou were going to hoist — is now 109 lines wrappingxbrlkit.parse.load_model.adapters/sec/processors/xbrl_graph.pywent 2,195 → 813 lines; the XBRL table schemas come fromxbrlkit.schema, and the EDGAR plugin, its tarballs and the EFM validation config are gone.So the first PR we agreed on — hoist
ArelleClient, SEC through a wrapper — no longer exists as a task. Good timing: you hadn't started it, so nothing is wasted. Sorry for not flagging it here when it landed.What that means for IND AS
The neutral layer you argued for in this RFC exists, and it's jurisdiction-neutral by construction rather than by refactor. xbrlkit loads a filing from a local path, directory, zip or URL; it resolves DTS from a persistent cache; it already reaches non-US filings — ESEF and the national regimes on filings.xbrl.org, addressed by LEI rather than CIK. There is no EDGAR assumption in the load path to work around.
That makes IND AS an xbrlkit question, not a RoboSystems one, which is why the issue is here now. It also collapses your v1:
adapters/xbrl/, noadapters/ind_as/, no graph materialization. Those were all scaffolding for the separation that already happened.ixtvariants. Plus a fixture and a loader test.That's a genuinely small, self-contained first contribution with no infrastructure attached to it.
And your actual goal gets closer than the RFC assumed
You said the point is exploring filings and asking questions over them with MCP/AI. xbrlkit ships that already:
is a local MCP server over the parsed filing —
describe_filing,resolve_element,fact_grid,statement,calculation,search_text,read_text. No graph, no index, no hosting, no key. The moment an IND AS filing loads cleanly, that works on it, and single-filing analysis needs nothing else built.What that does not give you is the cross-filer corpus — many companies, aggregate queries, trends. That's the RoboSystems side, it's the expensive hosted part (manifest, storage, ops, billing), and it stays where you put it in the RFC: out of v1, a product decision rather than a contribution. It also gets much cheaper once the engine parses the filings, since the SEC pipeline already runs through xbrlkit.
The framework path (
frameworks/ind-as/+ a bridge, for entities reporting under IND AS) is unaffected by any of this and stays in RoboSystems. You said corpus, so it's a separate conversation whenever it's wanted.Where to pick it up
Two things would help most:
Note the transfer dropped the
RFCtype and thearea:adapterslabel (they don't exist in this repo). The design discussion above is intact and still the reference for this work.