summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2023-03-06 15:24:51 +0100
committerCarlos Garnacho <carlosg@gnome.org>2023-03-19 22:54:02 +0100
commit2e40af7c5fbfc2c057487d12d1b926b11185b6ea (patch)
tree226cffa3f2be22898de79500734936160c0857f6 /docs
parenta9fb50417dd4cd5a8a00efdf5400cb63e8c07d8e (diff)
downloadtracker-2e40af7c5fbfc2c057487d12d1b926b11185b6ea.tar.gz
docs: Separate sandboxing documentation to its own doc
Explain this a bit better, add some diagrams, etc.
Diffstat (limited to 'docs')
-rw-r--r--docs/reference/libtracker-sparql/images/graph-example-diagram.dot28
-rw-r--r--docs/reference/libtracker-sparql/images/graph-example-diagram.svg90
-rw-r--r--docs/reference/libtracker-sparql/images/sandbox-diagram.dot45
-rw-r--r--docs/reference/libtracker-sparql/images/sandbox-diagram.svg102
-rw-r--r--docs/reference/libtracker-sparql/meson.build1
-rw-r--r--docs/reference/libtracker-sparql/overview.md25
-rw-r--r--docs/reference/libtracker-sparql/sandboxing.md.in120
7 files changed, 386 insertions, 25 deletions
diff --git a/docs/reference/libtracker-sparql/images/graph-example-diagram.dot b/docs/reference/libtracker-sparql/images/graph-example-diagram.dot
new file mode 100644
index 000000000..56827d7f3
--- /dev/null
+++ b/docs/reference/libtracker-sparql/images/graph-example-diagram.dot
@@ -0,0 +1,28 @@
+digraph {
+ rankdir=LR;
+ fontname="sans-serif";
+ compound=true;
+ node [shape="box", style="rounded", border=0, fontname="sans-serif"];
+
+ subgraph cluster_graph2 {
+ style="rounded";
+ color="lightgrey";
+ label = "example:B"
+ tooltip = "example:B"
+ fontsize=10;
+ item2[label="example:item2",tooltip="example:item2"];
+ type2[label="rdfs:Resource",tooltip="rdfs:Resource"];
+ item2 -> type2 [label="rdf:type",fontsize=10,fontname="sans-serif",tooltip="rdf:type",labeltooltip="rdf:type"];
+ }
+
+ subgraph cluster_graph1 {
+ style="rounded";
+ color="lightgrey";
+ label = "example:A"
+ tooltip = "example:A"
+ fontsize=10;
+ item1[label="example:item1",tooltip="example:item1"];
+ type1[label="rdfs:Resource",tooltip="rdfs:Resource"];
+ item1 -> type1 [label="rdf:type",fontsize=10,fontname="sans-serif",tooltip="rdf:type",labeltooltip="rdf:type"];
+ }
+}
diff --git a/docs/reference/libtracker-sparql/images/graph-example-diagram.svg b/docs/reference/libtracker-sparql/images/graph-example-diagram.svg
new file mode 100644
index 000000000..384bb9c57
--- /dev/null
+++ b/docs/reference/libtracker-sparql/images/graph-example-diagram.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 7.1.0 (0)
+ -->
+<!-- Pages: 1 -->
+<svg width="335pt" height="174pt"
+ viewBox="0.00 0.00 335.00 174.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 170)">
+<polygon fill="white" stroke="none" points="-4,4 -4,-170 331,-170 331,4 -4,4"/>
+<g id="clust1" class="cluster">
+<title>cluster_graph2</title>
+<g id="a_clust1"><a xlink:title="example:B">
+<path fill="none" stroke="lightgrey" d="M20,-8C20,-8 307,-8 307,-8 313,-8 319,-14 319,-20 319,-20 319,-67 319,-67 319,-73 313,-79 307,-79 307,-79 20,-79 20,-79 14,-79 8,-73 8,-67 8,-67 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="middle" x="163.5" y="-67" font-family="sans-serif" font-size="10.00">example:B</text>
+</a>
+</g>
+</g>
+<g id="clust2" class="cluster">
+<title>cluster_graph1</title>
+<g id="a_clust2"><a xlink:title="example:A">
+<path fill="none" stroke="lightgrey" d="M20,-87C20,-87 307,-87 307,-87 313,-87 319,-93 319,-99 319,-99 319,-146 319,-146 319,-152 313,-158 307,-158 307,-158 20,-158 20,-158 14,-158 8,-152 8,-146 8,-146 8,-99 8,-99 8,-93 14,-87 20,-87"/>
+<text text-anchor="middle" x="163.5" y="-146" font-family="sans-serif" font-size="10.00">example:A</text>
+</a>
+</g>
+</g>
+<!-- item2 -->
+<g id="node1" class="node">
+<title>item2</title>
+<g id="a_node1"><a xlink:title="example:item2">
+<path fill="none" stroke="black" d="M118,-52C118,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 118,-16 118,-16 124,-16 130,-22 130,-28 130,-28 130,-40 130,-40 130,-46 124,-52 118,-52"/>
+<text text-anchor="middle" x="73" y="-30.3" font-family="sans-serif" font-size="14.00">example:item2</text>
+</a>
+</g>
+</g>
+<!-- type2 -->
+<g id="node2" class="node">
+<title>type2</title>
+<g id="a_node2"><a xlink:title="rdfs:Resource">
+<path fill="none" stroke="black" d="M299,-52C299,-52 216,-52 216,-52 210,-52 204,-46 204,-40 204,-40 204,-28 204,-28 204,-22 210,-16 216,-16 216,-16 299,-16 299,-16 305,-16 311,-22 311,-28 311,-28 311,-40 311,-40 311,-46 305,-52 299,-52"/>
+<text text-anchor="middle" x="257.5" y="-30.3" font-family="sans-serif" font-size="14.00">rdfs:Resource</text>
+</a>
+</g>
+</g>
+<!-- item2&#45;&gt;type2 -->
+<g id="edge1" class="edge">
+<title>item2&#45;&gt;type2</title>
+<g id="a_edge1"><a xlink:title="rdf:type">
+<path fill="none" stroke="black" d="M130.25,-34C149.86,-34 172.02,-34 192.23,-34"/>
+<polygon fill="black" stroke="black" points="192.04,-37.5 202.04,-34 192.04,-30.5 192.04,-37.5"/>
+</a>
+</g>
+<g id="a_edge1&#45;label"><a xlink:title="rdf:type">
+<text text-anchor="middle" x="167" y="-37" font-family="sans-serif" font-size="10.00">rdf:type</text>
+</a>
+</g>
+</g>
+<!-- item1 -->
+<g id="node3" class="node">
+<title>item1</title>
+<g id="a_node3"><a xlink:title="example:item1">
+<path fill="none" stroke="black" d="M118,-131C118,-131 28,-131 28,-131 22,-131 16,-125 16,-119 16,-119 16,-107 16,-107 16,-101 22,-95 28,-95 28,-95 118,-95 118,-95 124,-95 130,-101 130,-107 130,-107 130,-119 130,-119 130,-125 124,-131 118,-131"/>
+<text text-anchor="middle" x="73" y="-109.3" font-family="sans-serif" font-size="14.00">example:item1</text>
+</a>
+</g>
+</g>
+<!-- type1 -->
+<g id="node4" class="node">
+<title>type1</title>
+<g id="a_node4"><a xlink:title="rdfs:Resource">
+<path fill="none" stroke="black" d="M299,-131C299,-131 216,-131 216,-131 210,-131 204,-125 204,-119 204,-119 204,-107 204,-107 204,-101 210,-95 216,-95 216,-95 299,-95 299,-95 305,-95 311,-101 311,-107 311,-107 311,-119 311,-119 311,-125 305,-131 299,-131"/>
+<text text-anchor="middle" x="257.5" y="-109.3" font-family="sans-serif" font-size="14.00">rdfs:Resource</text>
+</a>
+</g>
+</g>
+<!-- item1&#45;&gt;type1 -->
+<g id="edge2" class="edge">
+<title>item1&#45;&gt;type1</title>
+<g id="a_edge2"><a xlink:title="rdf:type">
+<path fill="none" stroke="black" d="M130.25,-113C149.86,-113 172.02,-113 192.23,-113"/>
+<polygon fill="black" stroke="black" points="192.04,-116.5 202.04,-113 192.04,-109.5 192.04,-116.5"/>
+</a>
+</g>
+<g id="a_edge2&#45;label"><a xlink:title="rdf:type">
+<text text-anchor="middle" x="167" y="-116" font-family="sans-serif" font-size="10.00">rdf:type</text>
+</a>
+</g>
+</g>
+</g>
+</svg>
diff --git a/docs/reference/libtracker-sparql/images/sandbox-diagram.dot b/docs/reference/libtracker-sparql/images/sandbox-diagram.dot
new file mode 100644
index 000000000..d8b9c505b
--- /dev/null
+++ b/docs/reference/libtracker-sparql/images/sandbox-diagram.dot
@@ -0,0 +1,45 @@
+graph {
+ rankdir=LR;
+ fontname="sans-serif";
+ compound=true;
+ node [shape="box", style="rounded", border=0, fontname="sans-serif"];
+
+ subgraph cluster_session {
+ style="rounded";
+ color="lightgrey";
+ label = "User session"
+ tooltip = "User session"
+ fontsize=10;
+
+ Portal;
+ node [shape="cylinder"];"Provider #1"; "Provider #2";
+
+ "Provider #1" -- Portal;
+ "Provider #2" -- Portal;
+ }
+
+ subgraph cluster_client1 {
+ style="dashed";
+ color="lightgrey";
+ label = "Sandbox #1"
+ tooltip = "Sandbox #1"
+ fontsize=10;
+ "App A";
+ node [shape="cylinder"]; "Provider #3";
+ "App A" -- "Provider #3";
+ }
+
+ subgraph cluster_client2 {
+ style="dashed";
+ color="lightgrey";
+ label = "Sandbox #2"
+ tooltip = "Sandbox #2"
+ fontsize=10;
+ "App B";
+ node [shape="cylinder";style="invis"]; "Provider #4";
+ "App B" -- "Provider #4" [style="invis"];
+ }
+
+ Portal -- "App A" [lhead=cluster_client1];
+ Portal -- "App B" [lhead=cluster_client2];
+}
diff --git a/docs/reference/libtracker-sparql/images/sandbox-diagram.svg b/docs/reference/libtracker-sparql/images/sandbox-diagram.svg
new file mode 100644
index 000000000..ac643ad10
--- /dev/null
+++ b/docs/reference/libtracker-sparql/images/sandbox-diagram.svg
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 7.1.0 (0)
+ -->
+<!-- Pages: 1 -->
+<svg width="443pt" height="174pt"
+ viewBox="0.00 0.00 443.00 174.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 170)">
+<polygon fill="white" stroke="none" points="-4,4 -4,-170 439,-170 439,4 -4,4"/>
+<g id="clust1" class="cluster">
+<title>cluster_session</title>
+<g id="a_clust1"><a xlink:title="User session">
+<path fill="none" stroke="lightgrey" d="M20,-20C20,-20 196,-20 196,-20 202,-20 208,-26 208,-32 208,-32 208,-133 208,-133 208,-139 202,-145 196,-145 196,-145 20,-145 20,-145 14,-145 8,-139 8,-133 8,-133 8,-32 8,-32 8,-26 14,-20 20,-20"/>
+<text text-anchor="middle" x="108" y="-133" font-family="sans-serif" font-size="10.00">User session</text>
+</a>
+</g>
+</g>
+<g id="clust2" class="cluster">
+<title>cluster_client1</title>
+<g id="a_clust2"><a xlink:title="Sandbox #1">
+<polygon fill="none" stroke="lightgrey" stroke-dasharray="5,2" points="228,-87 228,-158 427,-158 427,-87 228,-87"/>
+<text text-anchor="middle" x="327.5" y="-146" font-family="sans-serif" font-size="10.00">Sandbox #1</text>
+</a>
+</g>
+</g>
+<g id="clust3" class="cluster">
+<title>cluster_client2</title>
+<g id="a_clust3"><a xlink:title="Sandbox #2">
+<polygon fill="none" stroke="lightgrey" stroke-dasharray="5,2" points="228,-8 228,-79 427,-79 427,-8 228,-8"/>
+<text text-anchor="middle" x="327.5" y="-67" font-family="sans-serif" font-size="10.00">Sandbox #2</text>
+</a>
+</g>
+</g>
+<!-- Portal -->
+<g id="node1" class="node">
+<title>Portal</title>
+<path fill="none" stroke="black" d="M188,-91C188,-91 156,-91 156,-91 150,-91 144,-85 144,-79 144,-79 144,-67 144,-67 144,-61 150,-55 156,-55 156,-55 188,-55 188,-55 194,-55 200,-61 200,-67 200,-67 200,-79 200,-79 200,-85 194,-91 188,-91"/>
+<text text-anchor="middle" x="172" y="-69.3" font-family="sans-serif" font-size="14.00">Portal</text>
+</g>
+<!-- App A -->
+<g id="node4" class="node">
+<title>App A</title>
+<path fill="none" stroke="black" d="M279,-131C279,-131 248,-131 248,-131 242,-131 236,-125 236,-119 236,-119 236,-107 236,-107 236,-101 242,-95 248,-95 248,-95 279,-95 279,-95 285,-95 291,-101 291,-107 291,-107 291,-119 291,-119 291,-125 285,-131 279,-131"/>
+<text text-anchor="middle" x="263.5" y="-109.3" font-family="sans-serif" font-size="14.00">App A</text>
+</g>
+<!-- Portal&#45;&#45;App A -->
+<g id="edge5" class="edge">
+<title>Portal&#45;&#45;App A</title>
+<path fill="none" stroke="black" d="M200.34,-85.22C209.06,-89.12 218.84,-93.49 228,-97.58"/>
+</g>
+<!-- App B -->
+<g id="node6" class="node">
+<title>App B</title>
+<path fill="none" stroke="black" d="M279,-52C279,-52 248,-52 248,-52 242,-52 236,-46 236,-40 236,-40 236,-28 236,-28 236,-22 242,-16 248,-16 248,-16 279,-16 279,-16 285,-16 291,-22 291,-28 291,-28 291,-40 291,-40 291,-46 285,-52 279,-52"/>
+<text text-anchor="middle" x="263.5" y="-30.3" font-family="sans-serif" font-size="14.00">App B</text>
+</g>
+<!-- Portal&#45;&#45;App B -->
+<g id="edge6" class="edge">
+<title>Portal&#45;&#45;App B</title>
+<path fill="none" stroke="black" d="M200.34,-61.09C209.06,-57.28 218.84,-53.03 228,-49.03"/>
+</g>
+<!-- Provider #1 -->
+<g id="node2" class="node">
+<title>Provider #1</title>
+<path fill="none" stroke="black" d="M108,-114.73C108,-116.53 87.38,-118 62,-118 36.62,-118 16,-116.53 16,-114.73 16,-114.73 16,-85.27 16,-85.27 16,-83.47 36.62,-82 62,-82 87.38,-82 108,-83.47 108,-85.27 108,-85.27 108,-114.73 108,-114.73"/>
+<path fill="none" stroke="black" d="M108,-114.73C108,-112.92 87.38,-111.45 62,-111.45 36.62,-111.45 16,-112.92 16,-114.73"/>
+<text text-anchor="middle" x="62" y="-96.3" font-family="sans-serif" font-size="14.00">Provider #1</text>
+</g>
+<!-- Provider #1&#45;&#45;Portal -->
+<g id="edge1" class="edge">
+<title>Provider #1&#45;&#45;Portal</title>
+<path fill="none" stroke="black" d="M108.49,-88.63C120.48,-85.63 133.04,-82.49 143.74,-79.82"/>
+</g>
+<!-- Provider #2 -->
+<g id="node3" class="node">
+<title>Provider #2</title>
+<path fill="none" stroke="black" d="M108,-60.73C108,-62.53 87.38,-64 62,-64 36.62,-64 16,-62.53 16,-60.73 16,-60.73 16,-31.27 16,-31.27 16,-29.47 36.62,-28 62,-28 87.38,-28 108,-29.47 108,-31.27 108,-31.27 108,-60.73 108,-60.73"/>
+<path fill="none" stroke="black" d="M108,-60.73C108,-58.92 87.38,-57.45 62,-57.45 36.62,-57.45 16,-58.92 16,-60.73"/>
+<text text-anchor="middle" x="62" y="-42.3" font-family="sans-serif" font-size="14.00">Provider #2</text>
+</g>
+<!-- Provider #2&#45;&#45;Portal -->
+<g id="edge2" class="edge">
+<title>Provider #2&#45;&#45;Portal</title>
+<path fill="none" stroke="black" d="M108.49,-57.37C120.48,-60.37 133.04,-63.51 143.74,-66.18"/>
+</g>
+<!-- Provider #3 -->
+<g id="node5" class="node">
+<title>Provider #3</title>
+<path fill="none" stroke="black" d="M419,-127.73C419,-129.53 398.38,-131 373,-131 347.62,-131 327,-129.53 327,-127.73 327,-127.73 327,-98.27 327,-98.27 327,-96.47 347.62,-95 373,-95 398.38,-95 419,-96.47 419,-98.27 419,-98.27 419,-127.73 419,-127.73"/>
+<path fill="none" stroke="black" d="M419,-127.73C419,-125.92 398.38,-124.45 373,-124.45 347.62,-124.45 327,-125.92 327,-127.73"/>
+<text text-anchor="middle" x="373" y="-109.3" font-family="sans-serif" font-size="14.00">Provider #3</text>
+</g>
+<!-- App A&#45;&#45;Provider #3 -->
+<g id="edge3" class="edge">
+<title>App A&#45;&#45;Provider #3</title>
+<path fill="none" stroke="black" d="M291.35,-113C302.05,-113 314.66,-113 326.69,-113"/>
+</g>
+<!-- Provider #4 -->
+<!-- App B&#45;&#45;Provider #4 -->
+</g>
+</svg>
diff --git a/docs/reference/libtracker-sparql/meson.build b/docs/reference/libtracker-sparql/meson.build
index e49b31d8a..43f2e8880 100644
--- a/docs/reference/libtracker-sparql/meson.build
+++ b/docs/reference/libtracker-sparql/meson.build
@@ -89,6 +89,7 @@ endforeach
generated_content_files = [
'examples.md.in',
'tutorial.md.in',
+ 'sandboxing.md.in',
]
generated_content = []
diff --git a/docs/reference/libtracker-sparql/overview.md b/docs/reference/libtracker-sparql/overview.md
index 949d81c3f..cf183fe3d 100644
--- a/docs/reference/libtracker-sparql/overview.md
+++ b/docs/reference/libtracker-sparql/overview.md
@@ -32,28 +32,3 @@ one exposed by Tracker Miner FS, use [ctor@Tracker.SparqlConnection.bus_new].
To connect to another a database on a remote machine, use
[ctor@Tracker.SparqlConnection.remote_new]. This can be used to query online
databases that provide a SPARQL endpoint, such as [DBpedia](https://wiki.dbpedia.org/about).
- .
-## Connecting from Flatpak
-
-Tracker SPARQL provides a portal for the [Flatpak](https://flatpak.org/)
-application sandboxing system. This lets you control which parts of a
-database each app can query.
-
-The app's Flatpak manifest needs to specify which graph(s) the app will
-access. See the [example app](https://gitlab.gnome.org/GNOME/tracker/-/blob/master/examples/flatpak/org.example.TrackerSandbox.json)
-and the [portal documentation](https://gnome.pages.gitlab.gnome.org/tracker/docs/commandline/#tracker-xdg-portal-3) to see how.
-
-No code changes are needed in the app, as [ctor@Tracker.SparqlConnection.bus_new]
-will automatically try connect via the portal if it can't talk to the
-given D-Bus name directly.
-
-Tracker SPARQL is included in the
-[GNOME Flatpak SDK and runtime](https://docs.flatpak.org/en/latest/available-runtimes.html#gnome).
-If the app uses a different runtime, you may need to build Tracker
-SPARQL in the app manifest.
-
-The app might use the Tracker Miner FS search index. Ideally this is done via the portal,
-using the search index maintained on the host. Since not all OSes ship tracker-miner-fs-3,
-we recommend that apps bundle it inside the Flatpak and connect to the bundled version as
-a fallback. See [GNOME Music](https://gitlab.gnome.org/GNOME/gnome-music/)
-for an example of how to do this.
diff --git a/docs/reference/libtracker-sparql/sandboxing.md.in b/docs/reference/libtracker-sparql/sandboxing.md.in
new file mode 100644
index 000000000..02fdb0613
--- /dev/null
+++ b/docs/reference/libtracker-sparql/sandboxing.md.in
@@ -0,0 +1,120 @@
+Title: Sandboxing and portals
+slug: sandboxing-and-portals
+
+There are times when it does make sense to lend advanced querying
+capabilities around your data to other processes of the same machine,
+or even widely available to any application that might want to make
+use of it. One real life example of this is [Tracker Miners](https://gitlab.gnome.org/GNOME/tracker-miners)
+used as the [GNOME Desktop](https://gnome.org) indexer.
+
+But in this day and age, it is naive to make this data available
+without constraints on what data can be accessed. Tracker provides a
+portal for the [Flatpak](https://flatpak.org/) application sandboxing
+system. This provides the mechanisms to filter the available data for
+sandboxed users.
+
+# How it works
+
+The portal acts as a single entry point for sandboxed applications
+to have read access to any D-Bus SPARQL endpoint.
+
+<div class="docblock">
+{{ images/sandbox-diagram.svg }}
+</div>
+
+The partitioning of the data is decided by the data provider at
+the time of inserting this data in the RDF triple store, and relies
+on graphs as the natural partitioning scheme of RDF data. As an
+example, consider the following updates:
+
+```SPARQL
+INSERT DATA {
+ GRAPH example:A {
+ example:item1 a rdfs:Resource ;
+ }
+
+ GRAPH example:B {
+ example:item2 a rdfs:Resource ;
+ }
+}
+```
+
+Resulting in the following simple diagram:
+
+<div class="docblock">
+{{ images/graph-example-diagram.svg }}
+</div>
+
+At that point, SPARQL queries may target either, both or any graph, e.g.:
+
+```SPARQL
+# This will return example:item1
+SELECT ?element
+FROM example:A
+{
+ ?element a rdfs:Resource
+}
+```
+
+Or perhaps even poke at non-existing graphs:
+
+```SPARQL
+# This will return no elements
+SELECT ?element
+FROM example:C
+{
+ ?element a rdfs:Resource
+}
+```
+
+Graphs may overlap with other graphs, or extend each other.
+
+The data filtering performed by the portal strongly relies on these RDF
+semantics for graphs, except that graph access is enforced through the
+[`CONSTRAINT` syntax](sparql-and-tracker.html#constraint-syntax). These
+policies prevail over any other SPARQL syntax to specify graphs, and
+will result in filtered graphs being replaced by an empty graph.
+
+Likewise, notification of changes through [class@Tracker.Notifier] will
+be filtered on the way to sandboxed applications, so that there are only
+notifications on changes from the allowed graphs.
+
+# Using it from data providers
+
+Data providers are free to decide the data partitioning scheme available
+to sandboxed applications, by creating graphs and inserting data to
+those. Access to those graphs will be policied by the portal on their
+behalf.
+
+Keep in mind that there are limits on the [number of graphs](limits.html#limits-on-the-number-of-graphs)
+that apply on graph creation.
+
+# Using it from applications
+
+The portal is transparently integrated in the Tracker library. Applications
+may write SPARQL queries so that they work the same while sandboxed or not.
+No code changes are needed in the app, as [ctor@Tracker.SparqlConnection.bus_new]
+will automatically try connect via the portal if it can not talk to the
+given D-Bus name directly.
+
+The policy on the accessed graphs is usually defined in the flatpak manifest
+at the time of bundling the software, e.g.:
+
+```json
+{
+ "finish-args" : [
+ "--add-policy=Tracker3.dbus:org.example.Endpoint=example:A",
+ "--add-policy=Tracker3.dbus:org.example.Endpoint=example:B"
+ ]
+}
+```
+
+The portal will pick the policy from the `/.flatpak-info` file created
+by Flatpak, and (with the example arguments) allow access to graphs `example:A`
+and `example:B` from the `org.example.Endpoint` D-Bus SPARQL endpoint.
+Access to other graphs, or other services will be disallowed.
+
+The Tracker library is included in the
+[GNOME Flatpak SDK and runtime](https://docs.flatpak.org/en/latest/available-runtimes.html#gnome).
+If the app uses a different runtime, you may need to build Tracker
+SPARQL in the app manifest.