# Access Control Policy (ACP)

ESS uses [Access Control Policy (ACP)](/reference/glossary.md#access-control-policies) to manage access to Pod resources. With ACP, Pod owners can define Policies that determine access for their Pod’s resources.

### Policies

Policies determine access for Pod resources. A policy consists of:

* Matcher statements that specify conditions that must be satisfied for the Policy to take effect.
* Access mode statements that specify which access modes are allowed and/or denied to the agent(s) satisfying the Matcher statements.

{% code overflow="wrap" %}

```
If
< allOf | anyOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
< allOf | anyOf | noneOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
…

Then< allow ( [AccessMode(s)](acp.md#acp-access-modes) ) | deny ( [AccessMode(s)](acp.md#acp-access-modes) ) | allow ( [AccessMode(s)](acp.md#acp-access-modes) ) AND deny ( [AccessMode(s)](acp.md#acp-access-modes) ) >

```

{% endcode %}

{% hint style="warning" %}
Important

The **`noneOf()`** expression excludes matches from the **`allOf`** and **`anyOf`** expressions; i.e., you can use the **`noneOf`** expression to refine the **`allOf`** and **`anyOf`** matches.

Because the **`noneOf()`** expression acts as a secondary/supplementary filter to the **`allOf`** and **`anyOf`** expressions, a policy statement with only a **`noneOf(<matchers>)`** condition cannot be satisfied.
{% endhint %}

### Matcher Statements

{% code overflow="wrap" %}

```
< allOf | anyOf > ([Matcher(s)](acp.md#acp-matcher)) evaluate to true, AND
< allOf | anyOf | noneOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
…
```

{% endcode %}

#### Matchers

Matchers specify the conditions under which the Access Policy applies.

ESS supports matching:

<table><thead><tr><th width="114.37109375"></th><th></th></tr></thead><tbody><tr><td>Agents</td><td><ul><li>To match agents by specific <a href="https://docs.inrupt.com/reference/glossary#webid">WebID(s)</a>.</li><li>To match any authenticated agent.</li><li>To match any agent.</li></ul></td></tr><tr><td>Clients</td><td><ul><li>To match by specific <a href="/pages/vzCNW5vU72LdQziKR9gW#client-identifier-client-id">Client ID(s)</a>.</li><li>To match any client application.</li></ul><p>See also <a href="https://docs.inrupt.com/security/authentication#client-identifier-client-id">Authorization and Clients</a></p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Note<br>To use Client Matchers, the Policy must also specify an Agent Matcher.</p></div></td></tr><tr><td>Verifiable Credentials</td><td><ul><li>To match by <a href="https://docs.inrupt.com/reference/glossary#verifiable-credential">Verifiable Credential(s)</a> type; e.g., match VC type<strong><code>http://www.w3.org/ns/solid/vc#SolidAccessGrant</code></strong>.</li></ul><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong></p><p>To enable the use of ESS issued <a href="/pages/Y1dCA7Kh995mLodOh3Si">access grants (which are serialized as VCs)</a> , a policy with a VC Matcher is required. For details, see <a href="/pages/nzZgNhwDek5fJNZxuYts">access grants</a> .</p></div></td></tr></tbody></table>

#### allOf, anyOf, noneOf Operators

A policy specifies its matchers in **`allOf()`** , **`anyOf()`** , and **`noneOf()`** operator expressions.

| **`allOf(<matchers>)`**  | Evaluates to true if all of its listed matchers evaluate to true.  |
| ------------------------ | ------------------------------------------------------------------ |
| **`anyOf(<matchers>)`**  | Evaluates to true if any of its listed matchers evaluate to true.  |
| **`noneOf(<matchers>)`** | Evaluates to true if none of its listed matchers evaluate to true. |

{% hint style="warning" %}
Important\
The **`noneOf()`** expression excludes matches from the **`allOf`** and **`anyOf`** expressions; i.e., you can use the **`noneOf`** expression to refine the **`allOf`** and **`anyOf`** matches.

Because the **`noneOf()`** expression acts as a secondary/supplementary filter to the **`allOf`** and **`anyOf`** expressions, a policy statement with only a **`noneOf(<matchers>)`** condition cannot be satisfied.
{% endhint %}

### Access Mode Statements

{% code overflow="wrap" %}

```
< allow ( [AccessMode(s)](acp.md#acp-access-modes) ) | deny ( [AccessMode(s)](acp.md#acp-access-modes) ) |allow ( [AccessMode(s)](acp.md#acp-access-modes) ) AND deny ( [AccessMode(s)](acp.md#acp-access-modes) ) >
```

{% endcode %}

#### Access Modes

Access Modes describe the permissions that can be granted or denied. The available modes are:

| Access Mode  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`Read`**   | <p>Permission to view/retrieve a resource as well as to subscribe to <a href="/pages/nHjw9YkLxJtR7FE4JuM9">notifications</a> for the resource.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                   |
| **`Write`**  | <p>Permission to create a resource, update the content of a resource, and delete a resource.<br><br>Tip:<br>\* To create a resource, you must have <strong><code>Write</code></strong> access on both the resource and the resource’s container.<br>\* To delete a resource, you must have <strong><code>Write</code></strong> access on both the resource and the resource’s container.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p>                                                                                                                                                         |
| **`Append`** | <p>Permission to add content to a resource.<br>If a resource is a <a href="/pages/7PKZaxnnUDGdJ8gPDOqL#container">container</a> (analogous to a folder in a file system), the <strong><code>Append</code></strong> permission on the resource allows agents to add new resources (container, RDF resource, non-RDF resource) to the container.<br>If a resource is an <a href="/pages/Ejga65cCzJE3HowMncgm">RDF resource</a>, the <strong><code>Append</code></strong> permission on a resource allows agents to add statements to the resource.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p> |

#### allow, deny Expressions

A policy statement specifies its access modes in `allow(Access Modes)` or `deny(Access Modes)` expressions:

* The **`allow`** expression specifies the access modes to be granted.
* The **`deny`** expression specifies the access modes to be denied.

An agent is granted an access mode for a resource if:

* The agent satisfies a policy that allows the access mode for the resource, **and**
* The agent does not satisfy any policy that denies that access mode for the resource.

For example:

* If a resource only has a single policy that allows **`Read`** and **`Write`** for an agent, the agent is granted **`Read`** and **`Write`** for the resource.
* If a resource has:
  * A policy that allows **`Read`** and **`Write`** for an agent, and
  * A policy that denies **`Write`** for the same agent,

    Then, the agent is granted **`Read`** access for the resource.

If **no** “allow access” policy is satisfied for a resource, then that resource is inaccessible to the agent. That is, an unsatisfied “deny access” policy does not confer access. For example,

* If a resource has defined only a single policy that denies **`Read`** and the policy is unsatisfied by an agent, that agent still does not have any access to that resource.

#### CRUD Operations and Access Modes

This section summarizes the relationship between Create/Read/Update/Delete (CRUD) operations and the required access modes.

{% tabs %}
{% tab title="Create" %}
To create a resource, the user requires either an **`Append`** or **`Write`** access.

{% hint style="info" %}
Note The creation operation creates the resource (be it container, RDF resource, non-RDF resource) and updates the content of the **parent** container with the new resource’s metadata.
{% endhint %}

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](/reference/glossary.md#container)                                           | Either **`Append`** or **`Write`** access on the **parent** container (under which the new container is to be created) allows agents to create a new container. For example, to create `https://storage..../parentcontainer/newContainer/`, either an **`Append`** or a **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/newContainer/`.                                                      |
| [RDF resource](/reference/rdf.md)                                                       | Either **`Append`** or **`Write`** access on the **parent** container (under which the new resource is to be created) allows agents to create a RDF resource. For example, to create `https://storage..../parentcontainer/newResource/`, either an **`Append`** or a **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/newResource`.                                                           |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | Either **`Append`** or **`Write`** access on the **parent** container (under which the new resource is to be created) allows agents to create a new [non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource). For example, to create `https://storage..../parentcontainer/foo.jpg`, **`Append`** or **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/foo.jpg`. |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

{% tab title="Read" %}
For read operations , the user requires `Read` access.

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](/reference/glossary.md#container)                                           | **`Read`** access on the target container (analogous to a folder in a file system) allows agents to read/retrieve the container as a resource (not the resource(s) under the container). That is, Read access only affects read operation on the container itself. Reading a container (which stores metadata about the resources contained within the container) allows a client to discover what resources are contained inside the container and their resource type (i.e., analogous to an **`ls`** on a folder in a file system). |
| [RDF resource](/reference/rdf.md)                                                       | **`Read`** access on the RDF resource allows agents to read/retrieve the resource (regardless of the access on the parent container). For example, if a resource has as its URL `https://storage..../container/ResourceToRead`, to read/retrieve this resource: The user must have **`Read`** access on `https://storage..../container/ResourceToRead`. The user’s access on `https://storage..../container/` is immaterial.                                                                                                           |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | **`Read`** access on a non-RDF resource allows agents to read/retrieve the resource (regardless of Read access on the container). For example, if a non-RDF resource has as its URL `https://storage..../container/foo.jpg`, to read/retrieve this resource: The user must have **`Read`** access on `https://storage..../container/foo.jpg`. The user’s access on `https://storage..../container/` is immaterial.                                                                                                                     |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

{% tab title="Update" %}
For update operations, the user requires **`Append`** or **`Write`** access, depending on the specific update operation.

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](/reference/glossary.md#container)                                           | To add resources to the Container, see the Create tab. To delete resources from the Container, see the Delete tab.                                                                                                                                                                                                                                                                                                                        |
| [RDF resource](/reference/rdf.md)                                                       | Either **`Append`** or **`Write`** access on an RDF resource allows agents to add content (statements) to the resource. **`Write`** access on an RDF resource allows agents to delete content (statements) from the resource. **`Write`** access on an RDF resource allows agents to modify existing content (statements) in the resource.                                                                                                |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | **`Write`** access on the target resource allows agents to overwrite/replace the resource (regardless of the access on the parent container). For example, if the non-RDF resource has as its URL **`https://storage..../container/foo.jpg`**, to overwrite this resource: The user must have **`Write`** access on **`https://storage..../container/foo.jpg`**. The user’s access on **`https://storage..../container/`** is immaterial. |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                           |

{% tab title="Delete" %}
For delete operations, the user requires `Write` access.

| Resource                                                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](/reference/glossary.md#container)                       | **`Write`** access on both the parent container and the target container allows agents to delete the target container. For example, to delete `https://storage..../parentcontainer/containerToDelete/`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/containerToDelete/` allows agents to delete `https://storage..../parentcontainer/containerToDelete/`.                     |
| [RDF resource](/reference/rdf.md)                                   | To delete an RDF resource, **`Write`** access on both the parent container and the target resource allows agents to delete the target resource. For example, to delete `https://storage..../parentcontainer/resourceToDelete/`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/resourceToDelete` allows agents to delete `https://storage..../parentcontainer/resourceToDelete`. |
| [Non-RDF resource](/sdk/java-sdk/crud-rdf-data.md#non-rdf-resource) | To delete a non-RDF resource, **`Write`** access on both the parent container and the target resource allows agents to delete the target resource. For example, to delete `https://storage..../parentcontainer/foo.jpg`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/foo.jpg` allows agents to delete `https://storage..../parentcontainer/foo.jpg`.                          |
| {% endtab %}                                                        |                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| {% endtabs %}                                                       |                                                                                                                                                                                                                                                                                                                                                                                                                                              |

### Access Control Resource

Each Pod resource has an associated Access Control Resource (ACR) that contains the policies that determine access to the Pod resource.

<figure><img src="/files/PbUOCrnXnsrBbRUKzcZf" alt=""><figcaption></figcaption></figure>

The lifecycle of the ACR is bound to the lifecycle of the Pod resource; that is:

* When creating a resource, ESS creates a corresponding ACR.
* When deleting a resource, ESS deletes the corresponding ACR.

If a resource has no Policies that apply to it, the resource is inaccessible. However, the Pod owner can add new policies to provide access to the resource.

### Member Policies

If a resource is a Container, you can also specify Member Policies in the Container’s ACR. Member Policies will be inherited by the Container’s children/descendants.

### Access to ACRs

ESS’ [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) hosts the ACRs. The [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) ‘s [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) determines which clients can write policies to ACRs.

{% hint style="info" %}
Note\
Having read/write/append access to policies for a resource (i.e., write to the resource’s ACR) is distinct from having access to read/write/append the resource itself.
{% endhint %}

In version 2.0, ESS also uses the values in [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) as part of the initial ACP policies that determine the read/write/append access to the Pod and its resource.

Starting in 2.1, ESS uses the values in [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) if set. If unset, ESS uses the values in [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (same as it did in version 2.0).

For details, see [Initial ACP Policies](#initial-policies) .

### Initial ACP Policies

When a Pod is created, like any other Pod resource, an [Access Control Resource](#acp-acr) is also created for the Pod Root. The ACR is initialized with the default [ACP policies](#acp-policies) for the Pod Owner and for Access Grant enablement:

* **Initial Pod Owner policies** give the Pod Owner read and write access to the Pod. These policies also specify a client matcher as well if the **Authorization service’s** configuration for the initial client allow list is set:
  * [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) or if that is unset,
  * [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) .

{% tabs %}
{% tab title="Allow List is Set" %}
{% hint style="info" %}
**Note**

Starting in 2.1, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation) to create the client matcher for the initial ACP policies. If the configuration is unset, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation).
{% endhint %}

Using the value of the Pod owner’s WebID and an initial client allow list, ESS creates the initial policies of the form:

```
If allOf(AgentMatcher and ClientMatcher) evaluates to true, Then allow (Read and Write).
```

Specifically, ESS creates:

Policy 1 for the Pod Root:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , and if the client application’s Client ID has a match in the initial client allow list, allow Read and Write access.

Policy 2 for the Pod Root’s Initial Member Policies:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , and if the client application’s Client ID has a match in the initial client allow list, allow Read and Write access.

For more information on a Container’s Member Policies, see [Member Policies](#member-policies) .
{% endtab %}

{% tab title="Allow List is Not Set" %}
{% hint style="info" %}
**Note**\
Starting in 2.1, ESS uses the values in **Authorization service’s** [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation) to create the client matcher for the initial policies. If the configuration is unset, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation).
{% endhint %}

If the initial client allow list is empty (when creating the policy), ESS uses the value of the Pod owner’s WebID to create initial policies of the form:

```
If allOf(AgentMatcher) evaluates to true, Then allow (Read and Write).
```

Specifically, ESS creates:

Policy 1 for the Pod Root:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , allow Read and Write access.

Policy 2 for the Pod Root’s Initial Member Policies:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , allow Read and Write access.

For more information on a Container’s Member Policies, see [Member Policies](#member-policies) .
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**Disambiguation**\
Both [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) and [Pod Storage Service](/ess/latest/services/service-pod-management/service-pod-storage.md) have a `INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST` setting.

**Only** the [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) setting affects which clients are allowed. The [Pod Storage Service](/ess/latest/services/service-pod-management/service-pod-storage.md) is for [Discovery](/ess/latest/services/service-pod-management/service-pod-provision.md) purposes only.
{% endhint %}

* **Initial Access Grant Enablement policies** allow the use of [Access Grants](/security/authorization/access-requests-grants.md) that grant read/write/append access to the Pod resources. *New in Version 2.2*

  ```
        If allOf(VC Matcher) evaluates to true, Then allow (Read and Write and Append).
  ```

  Specifically, ESS creates:

Policy 3 for the Pod Root:If a presented VC matches the specified type, allow its use for\
Read, Write, and Append access.

Policy 4 for the Pod Root’s Initial Member Policies:If a presented VC matches the specified type, allow its use for\
Read, Write, and Append access.\
See also[`INRUPT_AUTHORIZATION_DEFAULT_ACR_ACCESS_GRANTS_ALLOWED_MODES`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_ACCESS_GRANTS_ALLOWED_MODES).

{% hint style="warning" %}
**Important**

The policies only enable the use of [Access Grants](/security/authorization/access-requests-grants.md) for the allowed access modes. To determine the access for an agent using an access grant, ESS uses the *intersection* of:

* The allowed access specified by the policy, and
* The granted access specified in the Access Grant (for the resource specified in the Access Grant).
  {% endhint %}

{% hint style="info" %}
Note\
A Pod’s initial Policies are set when the Pod is provisioned. As such, updates to the various `INRUPT_AUTHORIZATION_DEFAULT_ACR_*` options do not affect existing Pods.

That is, once a Pod’s initial policies have been created, changes to the various `INRUPT_AUTHORIZATION_DEFAULT_ACR_*` options are not reflected in that Pod’s policies.
{% endhint %}

* ESS’ ACP is based on an earlier version of the [Access Control Policy (ACP) Specification](https://solid.github.io/authorization-panel/acp-specification/) .
* Inrupt does not provide support for ESS servers running [Web Access Control (WAC)](https://solid.github.io/web-access-control-spec/) in Production.

### Examples

#### Create Policy to Match Agents and Clients

The following example sets up an **`app-friends-policy`** that allow Read and Write access to any Agent that satisfies the **`match-app-friends`** Matcher conditions; namely, Agents whose WebID matches one of the specified WebIDs and is using an application whose Client Identifier matches the specified Client IDs. When verifying against a policy that specifies a Client Application Matcher, the user must be logged in. A Policy that specifies a Client Application Matcher but no Agent Matcher does not match any agent.

{% code fullWidth="false" %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2, asUrl } from "@inrupt/solid-client";


// ... Various logic, including login logic, omitted for brevity.
// ...


async function setupPolicyToMatchAgentsAndClients(resourceURL) {

  const agentsToMatch = [ "https://id.example.com/chattycarl", "https://id.example.com/busybee" ];
  const clientIDsToMatch = [ "https://myapp.example.net/appid" ];

  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,            // Resource whose ACR to set up
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Initialize a new Matcher.
    let appFriendsMatcher = acp_ess_2.createResourceMatcherFor(
      resourceWithAcr,
      "match-app-friends"
    );

    // 3. For the Matcher, specify the Agent(s) to match.
    agentsToMatch.forEach(agent => {
      appFriendsMatcher = acp_ess_2.addAgent(appFriendsMatcher, agent);
    })

    // 4. For the Matcher, specify the Client ID(s) to match.
    clientIDsToMatch.forEach(clientID => {
      appFriendsMatcher = acp_ess_2.addClient(appFriendsMatcher, clientID);
    })

    // 5. Add the Matcher definition to the Resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
      resourceWithAcr,
      appFriendsMatcher
    );

    // 6. Create a Policy for the Matcher.
    let appFriendsPolicy = acp_ess_2.createResourcePolicyFor(
      resourceWithAcr,
      "app-friends-policy",
    );

    // 7. Add the appFriendsMatcher to the Policy as an allOf() expression.
    // Since using allOf() with a single Matcher, could also use anyOf() expression

    appFriendsPolicy = acp_ess_2.addAllOfMatcherUrl(
      appFriendsPolicy,
      appFriendsMatcher
    );

    // 8. Specify the access modes (e.g., allow Read and Write).
    appFriendsPolicy = acp_ess_2.setAllowModes(appFriendsPolicy,
      { read: true, write: true }
    );

    // 9. Apply the Policy to the resource.
    resourceWithAcr = acp_ess_2.addPolicyUrl(
      resourceWithAcr,
      asUrl(appFriendsPolicy)
    );

    // 10. Add the Policy definition to the resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      appFriendsPolicy
    );

    // 11. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

{% endcode %}

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,            // Resource whose ACR to set up
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.createResourceMatcherFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcematcherfor) to initialize the Matcher that will be used by the policy.

   ```javascript
   let appFriendsMatcher = acp_ess_2.createResourceMatcherFor(
     resourceWithAcr,
     "match-app-friends"
   );
   ```

   When saved, the Matcher URL will be `{ACR URL}#match-app-friends`.
3. [acp\_ess\_2.addAgent](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addagent) to specify the [WebID](about:blank/reference/glossary/#term-WebID) of the agent(s) to match:

   ```javascript
   agentsToMatch.forEach(agent => {
     appFriendsMatcher = acp_ess_2.addAgent(appFriendsMatcher, agent);
   })
   ```
4. [acp\_ess\_2.addClient](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addclient) to specify the [Client ID](about:blank/authenticate-client/#authenticate-client-identifier-document) of the application(s) to match.

   ```javascript
   clientIDsToMatch.forEach(clientID => {
     appFriendsMatcher = acp_ess_2.addClient(appFriendsMatcher, clientID);
   })
   ```
5. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to store the new matcher definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourceMatcher(
     resourceWithAcr,
     appFriendsMatcher
   );
   ```
6. [acp\_ess\_2.createResourcePolicyFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcepolicyfor) to initialize the policy:

   ```javascript
   let appFriendsPolicy = acp_ess_2.createResourcePolicyFor(
     resourceWithAcr,
     "app-friends-policy",
   );
   ```

   When saved, the policy URL will be `{ACR URL}#app-friends-policy`.
7. [acp\_ess\_2.addAllOfMatcherUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addallofmatcherurl) to add the matcher to the policy.

   ```javascript
   // Since using allOf() with a single Matcher, could also use anyOf() expression

   appFriendsPolicy = acp_ess_2.addAllOfMatcherUrl(
     appFriendsPolicy,
     appFriendsMatcher
   );
   ```
8. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to specify that the policy allows `Read` and `Write` modes:

   ```javascript
   appFriendsPolicy = acp_ess_2.setAllowModes(appFriendsPolicy,
     { read: true, write: true }
   );
   ```
9. [acp\_ess\_2.addPolicyUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addpolicyurl) to apply the new policy to the resource:

   ```javascript
   resourceWithAcr = acp_ess_2.addPolicyUrl(
     resourceWithAcr,
     asUrl(appFriendsPolicy)
   );
   ```
10. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to store the new policy definition to the ACR:

    ```javascript
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      appFriendsPolicy
    );
    ```
11. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

    ```javascript
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
    ```

#### Make a Resource Public: Create Public Policy for a Resource

The following example uses the ACP-specific APIs to set up a **`public-policy`** that allows Read access to the public (i.e., everyone) for a resource.

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.
// ...

async function setupPublicReadPolicyForResource(resourceURL) {
  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,              // Resource for which to set up the policies
      { fetch: fetch }          // fetch from the authenticated session
    );

    // 2. Create a Matcher for the Resource.
    let resourcePublicMatcher = acp_ess_2.createResourceMatcherFor(
      resourceWithAcr,
      "match-public"  // Matcher URL will be {ACR URL}#match-public
    );

    // 3. Specify that the matcher matches the Public (i.e., everyone).
    resourcePublicMatcher = acp_ess_2.setPublic(resourcePublicMatcher);

    // 4. Add Matcher to the Resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
      resourceWithAcr,
      resourcePublicMatcher,
    );

    // 5. Create the Policy for the Resource.
    let resourcePolicy = acp_ess_2.createResourcePolicyFor(
      resourceWithAcr,
      "public-policy",  // Policy URL will be {ACR URL}#public-policy
    );

    // 6. Add the Public Matcher to the Policy as an allOf() expression.
    resourcePolicy = acp_ess_2.addAllOfMatcherUrl(
      resourcePolicy,
      resourcePublicMatcher
    );

    // 7. Specify the access modes for the Policy.
    resourcePolicy = acp_ess_2.setAllowModes(
      resourcePolicy,
      { read: true, append: false, write: false },
    );

    // 8. Apply the Policy to the Resource.
    resourceWithAcr = acp_ess_2.addPolicyUrl(
       resourceWithAcr,
       asUrl(resourcePolicy)
     );

    // 9. Add the Policy definition to the Resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
       resourceWithAcr,
       resourcePolicy,
    );

    // 10. Save the ACR for the Resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,              // Resource for which to set up the policies
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.createResourceMatcherFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcematcherfor) to initialize the Matcher that will be used by the policy.

   ```javascript
   let resourcePublicMatcher = acp_ess_2.createResourceMatcherFor(
     resourceWithAcr,
     "match-public"  // Matcher URL will be {ACR URL}#match-public
   );
   ```

   When saved, the Matcher URL will be `{ACR URL}#match-public`.
3. [acp\_ess\_2.setPublic](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setpublic) to specify that the matcher is a Public matcher; i.e., matches everyone.

   ```javascript
   resourcePublicMatcher = acp_ess_2.setPublic(resourcePublicMatcher);
   ```
4. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to store the matcher definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourceMatcher(
     resourceWithAcr,
     resourcePublicMatcher,
   );
   ```
5. [acp\_ess\_2.createResourcePolicyFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcepolicyfor) to initialize the policy for the Resource:

   ```javascript
   let resourcePolicy = acp_ess_2.createResourcePolicyFor(
     resourceWithAcr,
     "public-policy",  // Policy URL will be {ACR URL}#public-policy
   );
   ```

   When saved, the policy URL will be `{ACR URL}#public-policy`.
6. [acp\_ess\_2.addAllOfMatcherUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addallofmatcherurl) to add the matcher to the policy.

   ```javascript
   resourcePolicy = acp_ess_2.addAllOfMatcherUrl(
     resourcePolicy,
     resourcePublicMatcher
   );
   ```
7. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to specify the access modes for the policy:

   ```javascript
   resourcePolicy = acp_ess_2.setAllowModes(
     resourcePolicy,
     { read: true, append: false, write: false },
   );
   ```
8. [acp\_ess\_2.addPolicyUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addpolicyurl) to apply the new policy to the resource:

   ```javascript
   resourceWithAcr = acp_ess_2.addPolicyUrl(
      resourceWithAcr,
      asUrl(resourcePolicy)
    );
   ```
9. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to store the new policy definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      resourcePolicy,
   );
   ```
10. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

    ```javascript
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
    ```

#### View Policies and Matchers for a Resource

The following example uses the ACP-specific APIs to view the ACP policies for a resource.

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2, solidDatasetAsTurtle } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function viewResourceACR(resourceURL) {

  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,
      { fetch: fetch }            // fetch from the authenticated session
    );

    // 2a. Get the Access Control Resource (ACR)
    const myACR = await getSolidDataset(
      acp_ess_2.getLinkedAcrUrl(resourceWithAcr),
      { fetch: fetch }
    );
    
    // 2b. Output (formatted as Turtle) its policies and matchers details.
    console.log(solidDatasetAsTurtle(myACR));

    // 3a. Get all policies from the ACR to process policies.
    const myResourcePolicies = acp_ess_2.getResourcePolicyAll(resourceWithAcr);

    // Loop through each policy for processing.
    myResourcePolicies.forEach(policy => {
      //... 
    });

    // 3b. Get a specific policy from the ACR.
    const specificPolicy = acp_ess_2.getResourcePolicy(
      resourceWithAcr,
      "specify-the-name-of-policy-to-get"
    );

    // 4a. Get all matchers from the ACR to process matchers.
    const myResourceMatchers = acp_ess_2.getResourceMatcherAll(resourceWithAcr)

    // Loop through each matcher for processing.
    myResourceMatchers.forEach(matcher => {
      // ... 
    });

    // 4b. Get a specific matcher from the ACR.
    const specificMatcher = acp_ess_2.getResourceMatcher(
      resourceWithAcr,
      "specify-the-name-of-matcher-to-get"
    );


  } catch (error) {
      console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   const resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,
     { fetch: fetch }            // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) with [getLinkedAcrUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getlinkedacrurl) to retrieve the ACR.

   ```javascript
   const myACR = await getSolidDataset(
     acp_ess_2.getLinkedAcrUrl(resourceWithAcr),
     { fetch: fetch }
   );
   ```

   Once you retrieve the ACR as a SolidDataset, you can use [solidDatasetAsTurtle](https://inrupt.github.io/solid-client-js/modules/formats.html#soliddatasetasturtle) to format ACR as [Turtle](https://www.w3.org/TR/turtle/).

   ```javascript
   console.log(solidDatasetAsTurtle(myACR));
   ```
3. [acp\_ess\_2.getResourcePolicyAll](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicyall) to get the policies from the resource’s ACR.

   ```javascript
   const myResourcePolicies = acp_ess_2.getResourcePolicyAll(resourceWithAcr);

   // Loop through each policy for processing.
   myResourcePolicies.forEach(policy => {
     //... 
   });
   ```

   To view a specific policy, you can use [acp\_ess\_2.getResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicy):

   ```javascript
   const specificPolicy = acp_ess_2.getResourcePolicy(
     resourceWithAcr,
     "specify-the-name-of-policy-to-get"
   );
   ```
4. [acp\_ess\_2.getResourceMatcherAll](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcherall) to get all matchers from the resource’s ACR.

   ```javascript
   const myResourceMatchers = acp_ess_2.getResourceMatcherAll(resourceWithAcr)

   // Loop through each matcher for processing.
   myResourceMatchers.forEach(matcher => {
     // ... 
   });
   ```

   To view a specific matcher, you can use [acp\_ess\_2.getResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcher):

   ```javascript
   const specificMatcher = acp_ess_2.getResourceMatcher(
     resourceWithAcr,
     "specify-the-name-of-matcher-to-get"
   );
   ```

#### Delete Existing Policy for a Resource

The following example deletes an existing Policy for a resource.

{% hint style="info" %}
**Tip**

To view existing Policies for a resource, see View Policies and Matchers for a Resource.
{% endhint %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function deletePolicyForResource(resourceURL, policyName) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,           // Resource whose policy you want to delete
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Remove the Policy definition from the ACR
    resourceWithAcr = acp_ess_2.removeResourcePolicy(resourceWithAcr, policyName);

    // 3. Save the ACR for the Resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,           // Resource whose policy you want to delete
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.removeResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeresourcepolicy) to delete the Policy definition from the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.removeResourcePolicy(resourceWithAcr, policyName);
   ```

   [acp\_ess\_2.removeResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeresourcepolicy) can also accept the Policy URL or the Policy itself instead of the Policy name.
3. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

#### Modify Existing Matcher for a Resource

The following example continues from an earlier example. Specifically, the example modifies the **`match-app-friends`** created in [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients) to remove one of the Agents from the match list.

Tip

To view existing Matchers for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function removeAgentFromMatcher(resourceURL) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
        resourceURL,           // Resource whose Matcher you want to modify
        { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Get the Matcher to modify.
    let matcherToModify = acp_ess_2.getResourceMatcher(
        resourceWithAcr,
        "match-app-friends" // Name of the Matcher created in an earlier example.
    );

    // 3. Modify the Matcher; e.g., remove an Agent from the Matcher.

    const agentToRemove="https://id.example.com/chattycarl";
    matcherToModify = acp_ess_2.removeAgent(matcherToModify, agentToRemove);

    // 4. Store the modified Matcher definition to the resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
        resourceWithAcr,
        matcherToModify
    );

    // 5. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
        resourceWithAcr,
        { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

#### **Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
       resourceURL,           // Resource whose Matcher you want to modify
       { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.getResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcher) to get the Matcher from the resource’s ACR.

   ```javascript
   let matcherToModify = acp_ess_2.getResourceMatcher(
       resourceWithAcr,
       "match-app-friends" // Name of the Matcher created in an earlier example.
   );
   ```

   The `match-app-friends` was created in an earlier example, [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients).

   Tip

   To view existing Matchers for a resource, see [View Policies and Matchers for a Resource](https://docs.inrupt.com/security/authorization/acp#view-policies-and-matchers-for-a-resource).
3. [acp\_ess\_2.removeAgent](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeagent) to remove an Agent’s WebID from the list of the Matcher’s WebIDs to match.

   ```javascript
   policyToModify = acp_ess_2.setAllowModes(policyToModify,
     { write: false }
   );
   ```
4. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to update the Matcher definition in the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
     resourceWithAcr,
     policyToModify
   );
   ```
5. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

#### Modify Existing Policy for a Resource

The following example continues from an earlier example. Specifically, the example modifies the **`app-friends-policy`** created in [Create Policy to Match Agents and Client](#create-policy-to-match-agents-and-clients).

{% hint style="info" %}
Tip

To view existing Policies for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).
{% endhint %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function modifyAppFriendsPolicy(resourceURL) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,           // Resource whose Policy you want to modify
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Get the Policy to modify. 
    let policyToModify = acp_ess_2.getResourcePolicy(
      resourceWithAcr,
      "app-friends-policy" // Name of the Policy created in an earlier example.
    );

    // 3. Change the Write access mode to false (from true). Other access modes remain unchanged.
    policyToModify = acp_ess_2.setAllowModes(policyToModify,
      { write: false }
    );

    // 4. Store the modified Policy definition to the resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      policyToModify
    );

    // 5. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,           // Resource whose Policy you want to modify
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.getResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicy) to get the Policy from the resource’s ACR. The `app-friends-policy` was created in an earlier example, [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients).

   ```javascript
   let policyToModify = acp_ess_2.getResourcePolicy(
     resourceWithAcr,
     "app-friends-policy" // Name of the Policy created in an earlier example.
   );
   ```

   Tip

   To view existing Policies for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).
3. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to update the Write access mode for the Policy. The other Access Modes for this Policy remain unchanged.

   ```javascript
   policyToModify = acp_ess_2.setAllowModes(policyToModify,
     { write: false }
   );
   ```

   For additional Policy functions, see the [API documentation](https://inrupt.github.io/solid-client-js/).
4. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to update the Policy definition in the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
     resourceWithAcr,
     policyToModify
   );
   ```
5. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.inrupt.com/security/authorization/acp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
