diff --git a/rocrate/model/entity.py b/rocrate/model/entity.py
index 41bf09b..fa26218 100644
--- a/rocrate/model/entity.py
+++ b/rocrate/model/entity.py
@@ -30,9 +30,9 @@ class Entity(MutableMapping):
     def __init__(self, crate, identifier=None, properties=None):
         self.crate = crate
         if identifier:
-            self.id = self.format_id(identifier)
+            self.__id = self.format_id(identifier)
         else:
-            self.id = f"#{uuid.uuid4()}"
+            self.__id = f"#{uuid.uuid4()}"
         if properties:
             empty = self._empty()
             empty.update(properties)
@@ -40,6 +40,10 @@ class Entity(MutableMapping):
         else:
             self._jsonld = self._empty()
 
+    @property
+    def id(self):
+        return self.__id
+
     # Format the given ID with rules appropriate for this type.
     # For example, Dataset (directory) data entities SHOULD end with /
     def format_id(self, identifier):

diff --git a/test/test_model.py b/test/test_model.py
index e7b5343..9f00a48 100644
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -505,3 +505,10 @@ def test_add_no_duplicates(test_data_dir, tmpdir):
     assert ret["name"] == "Jim"
     assert ret in crate.get_entities()
     assert crate.contextual_entities == [jim]
+
+
+def test_immutable_id():
+    crate = ROCrate()
+    p = crate.add(Person(crate, "#foo"))
+    with pytest.raises(AttributeError):
+        p.id = "#bar"

Entity id should not be modifiable
It's used to index the entity in the crate's `__entity_map`, so changing it leads to inconsistencies:

```pycon
>>> from rocrate.rocrate import ROCrate
>>> crate = ROCrate()
>>> d = crate.add_dataset("FOO")
>>> crate._ROCrate__entity_map
{..., 'arcp://uuid,2f145cc1-20be-4cd7-ac86-d6d4a08cdcf9/FOO': <FOO/ Dataset>}
>>> d.id = "foo"
>>> crate._ROCrate__entity_map
{..., 'arcp://uuid,2f145cc1-20be-4cd7-ac86-d6d4a08cdcf9/FOO': <foo Dataset>}
>>> crate.dereference("foo")
>>> crate.dereference("FOO")
<foo Dataset>

```
test/test_model.py::test_immutable_id
test/test_model.py::test_dereferencing test/test_model.py::test_dereferencing_equivalent_id[.foo] test/test_model.py::test_dereferencing_equivalent_id[foo.] test/test_model.py::test_dereferencing_equivalent_id[.foo/] test/test_model.py::test_dereferencing_equivalent_id[foo./] test/test_model.py::test_data_entities test/test_model.py::test_data_entities_perf test/test_model.py::test_remote_data_entities test/test_model.py::test_bad_data_entities test/test_model.py::test_contextual_entities test/test_model.py::test_contextual_entities_hash test/test_model.py::test_properties test/test_model.py::test_uuid test/test_model.py::test_update test/test_model.py::test_delete test/test_model.py::test_delete_refs test/test_model.py::test_delete_by_id test/test_model.py::test_self_delete test/test_model.py::test_entity_as_mapping test/test_model.py::test_wf_types test/test_model.py::test_append_to[False] test/test_model.py::test_append_to[True] test/test_model.py::test_get_by_type test/test_model.py::test_context test/test_model.py::test_add_no_duplicates