diff --git a/packages/pds/package.json b/packages/pds/package.json
index 38fab3e6..a2ab5efe 100644
--- a/packages/pds/package.json
+++ b/packages/pds/package.json
@@ -43,7 +43,7 @@
     "@atproto/syntax": "workspace:^",
     "@atproto/xrpc": "workspace:^",
     "@atproto/xrpc-server": "workspace:^",
-    "@did-plc/lib": "^0.0.1",
+    "@did-plc/lib": "^0.0.4",
     "better-sqlite3": "^7.6.2",
     "bytes": "^3.1.2",
     "compression": "^1.7.4",
diff --git a/packages/pds/src/api/com/atproto/server/createAccount.ts b/packages/pds/src/api/com/atproto/server/createAccount.ts
index adfdab3b..c8f47a0d 100644
--- a/packages/pds/src/api/com/atproto/server/createAccount.ts
+++ b/packages/pds/src/api/com/atproto/server/createAccount.ts
@@ -2,12 +2,12 @@ import { DidDocument, MINUTE, check } from '@atproto/common'
 import { AtprotoData, ensureAtpDocument } from '@atproto/identity'
 import { InvalidRequestError } from '@atproto/xrpc-server'
 import { ExportableKeypair, Keypair, Secp256k1Keypair } from '@atproto/crypto'
+import * as plc from '@did-plc/lib'
 import disposable from 'disposable-email'
 import {
   baseNormalizeAndValidate,
   normalizeAndValidateHandle,
 } from '../../../../handle'
-import * as plc from '@did-plc/lib'
 import { Server } from '../../../../lexicon'
 import { InputSchema as CreateAccountInput } from '../../../../lexicon/types/com/atproto/server/createAccount'
 import AppContext from '../../../../context'
@@ -101,7 +101,12 @@ const validateInputsForEntrywayPds = async (
       'IncompatibleDidDoc',
     )
   }
-  await plc.assureValidOp(plcOp)
+  try {
+    await plc.assureValidOp(plcOp)
+    await plc.assureValidSig([plcRotationKey], plcOp)
+  } catch (err) {
+    throw new InvalidRequestError('invalid plc operation', 'IncompatibleDidDoc')
+  }
   const doc = plc.formatDidDoc({ did, ...plcOp })
   const data = ensureAtpDocument(doc)
 
diff --git a/packages/pds/tests/entryway.test.ts b/packages/pds/tests/entryway.test.ts
index 8d2c03dc..dc3ba5c7 100644
--- a/packages/pds/tests/entryway.test.ts
+++ b/packages/pds/tests/entryway.test.ts
@@ -1,5 +1,6 @@
 import * as os from 'node:os'
 import * as path from 'node:path'
+import * as plcLib from '@did-plc/lib'
 import AtpAgent from '@atproto/api'
 import { Secp256k1Keypair, randomStr } from '@atproto/crypto'
 import { SeedClient, TestPds, TestPlc, mockResolvers } from '@atproto/dev-env'
@@ -131,6 +132,28 @@ describe('entryway', () => {
     expect(accountFromPds?.handle).toEqual('alice3.test')
     expect(accountFromEntryway?.handle).toEqual('alice3.test')
   })
+
+  it('does not allow bringing own op to account creation.', async () => {
+    const {
+      data: { signingKey },
+    } = await pdsAgent.api.com.atproto.server.reserveSigningKey({})
+    const rotationKey = await Secp256k1Keypair.create()
+    const plcCreate = await plcLib.createOp({
+      signingKey,
+      rotationKeys: [rotationKey.did(), entryway.ctx.plcRotationKey.did()],
+      handle: 'weirdalice.test',
+      pds: pds.ctx.cfg.service.publicUrl,
+      signer: rotationKey,
+    })
+    const tryCreateAccount = pdsAgent.api.com.atproto.server.createAccount(
+      { did: plcCreate.did, plcOp: plcCreate.op, handle: 'weirdalice.test' },
+      {
+        headers: SeedClient.getHeaders(accessToken),
+        encoding: 'application/json',
+      },
+    )
+    await expect(tryCreateAccount).rejects.toThrow('invalid plc operation')
+  })
 })
 
 const createEntryway = async (
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2c8be3e7..860cce53 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -401,7 +401,7 @@ importers:
     devDependencies:
       ts-node:
         specifier: ^10.8.1
-        version: 10.8.2(@swc/core@1.3.42)(@types/node@18.17.8)(typescript@4.9.5)
+        version: 10.8.2(@swc/core@1.3.42)(@types/node@20.10.4)(typescript@5.3.3)
 
   packages/identity:
     dependencies:
@@ -506,8 +506,8 @@ importers:
         specifier: workspace:^
         version: link:../xrpc-server
       '@did-plc/lib':
-        specifier: ^0.0.1
-        version: 0.0.1
+        specifier: ^0.0.4
+        version: 0.0.4
       better-sqlite3:
         specifier: ^7.6.2
         version: 7.6.2
@@ -782,7 +782,7 @@ importers:
         version: 4.20.0
       opentelemetry-plugin-better-sqlite3:
         specifier: ^1.1.0
-        version: 1.1.0(better-sqlite3@7.6.2)
+        version: 1.1.0(better-sqlite3@9.2.2)
 
 packages:
 
@@ -807,6 +807,14 @@ packages:
       pino: 8.15.0
       zod: 3.21.4
 
+  /@atproto/common@0.1.1:
+    resolution: {integrity: sha512-GYwot5wF/z8iYGSPjrLHuratLc0CVgovmwfJss7+BUOB6y2/Vw8+1Vw0n9DDI0gb5vmx3UI8z0uJgC8aa8yuJg==}
+    dependencies:
+      '@ipld/dag-cbor': 7.0.3
+      multiformats: 9.9.0
+      pino: 8.15.0
+      zod: 3.21.4
+
   /@atproto/crypto@0.1.0:
     resolution: {integrity: sha512-9xgFEPtsCiJEPt9o3HtJT30IdFTGw5cQRSJVIy5CFhqBA4vDLcdXiRDLCjkzHEVbtNCsHUW6CrlfOgbeLPcmcg==}
     dependencies:
@@ -853,7 +861,7 @@ packages:
       p-queue: 6.6.2
       pg: 8.10.0
       pino: 8.15.0
-      pino-http: 8.4.0
+      pino-http: 8.2.1
       sharp: 0.31.3
       typed-emitter: 2.1.0
       uint8arrays: 3.0.0
@@ -4686,7 +4694,20 @@ packages:
       '@atproto/common': 0.1.0
       '@atproto/crypto': 0.1.0
       '@ipld/dag-cbor': 7.0.3
-      axios: 1.4.0
+      axios: 1.6.2
+      multiformats: 9.9.0
+      uint8arrays: 3.0.0
+      zod: 3.21.4
+    transitivePeerDependencies:
+      - debug
+
+  /@did-plc/lib@0.0.4:
+    resolution: {integrity: sha512-Omeawq3b8G/c/5CtkTtzovSOnWuvIuCI4GTJNrt1AmCskwEQV7zbX5d6km1mjJNbE0gHuQPTVqZxLVqetNbfwA==}
+    dependencies:
+      '@atproto/common': 0.1.1
+      '@atproto/crypto': 0.1.0
+      '@ipld/dag-cbor': 7.0.3
+      axios: 1.6.2
       multiformats: 9.9.0
       uint8arrays: 3.0.0
       zod: 3.21.4
@@ -4698,7 +4719,7 @@ packages:
     dependencies:
       '@atproto/common': 0.1.0
       '@atproto/crypto': 0.1.0
-      '@did-plc/lib': 0.0.1
+      '@did-plc/lib': 0.0.4
       axios: 1.4.0
       cors: 2.8.5
       express: 4.18.2
@@ -5566,6 +5587,12 @@ packages:
   /@types/node@18.17.8:
     resolution: {integrity: sha512-Av/7MqX/iNKwT9Tr60V85NqMnsmh8ilfJoBlIVibkXfitk9Q22D9Y5mSpm+FvG5DET7EbVfB40bOiLzKgYFgPw==}
 
+  /@types/node@20.10.4:
+    resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
+    dependencies:
+      undici-types: 5.26.5
+    dev: true
+
   /@types/nodemailer@6.4.6:
     resolution: {integrity: sha512-pD6fL5GQtUKvD2WnPmg5bC2e8kWCAPDwMPmHe/ohQbW+Dy0EcHgZ2oCSuPlWNqk74LS5BVMig1SymQbFMPPK3w==}
     dependencies:
@@ -6014,6 +6041,15 @@ packages:
     transitivePeerDependencies:
       - debug
 
+  /axios@1.6.2:
+    resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==}
+    dependencies:
+      follow-redirects: 1.15.3
+      form-data: 4.0.0
+      proxy-from-env: 1.1.0
+    transitivePeerDependencies:
+      - debug
+
   /b4a@1.6.4:
     resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==}
     dev: false
@@ -6164,6 +6200,14 @@ packages:
       bindings: 1.5.0
       prebuild-install: 7.1.1
 
+  /better-sqlite3@9.2.2:
+    resolution: {integrity: sha512-qwjWB46il0lsDkeB4rSRI96HyDQr8sxeu1MkBVLMrwusq1KRu4Bpt1TMI+8zIJkDUtZ3umjAkaEjIlokZKWCQw==}
+    requiresBuild: true
+    dependencies:
+      bindings: 1.5.0
+      prebuild-install: 7.1.1
+    dev: false
+
   /big-integer@1.6.51:
     resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==}
     engines: {node: '>=0.6'}
@@ -7614,7 +7658,6 @@ packages:
     resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==}
     dependencies:
       punycode: 1.4.1
-    dev: false
 
   /fast-xml-parser@4.0.11:
     resolution: {integrity: sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==}
@@ -7721,6 +7764,15 @@ packages:
       debug:
         optional: true
 
+  /follow-redirects@1.15.3:
+    resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+
   /for-each@0.3.3:
     resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
     dependencies:
@@ -9574,7 +9626,7 @@ packages:
       mimic-fn: 2.1.0
     dev: true
 
-  /opentelemetry-plugin-better-sqlite3@1.1.0(better-sqlite3@7.6.2):
+  /opentelemetry-plugin-better-sqlite3@1.1.0(better-sqlite3@9.2.2):
     resolution: {integrity: sha512-yd+mgaB5W5JxzcQt9TvX1VIrusqtbbeuxSoZ6KQe4Ra0J/Kqkp6kz7dg0VQUU5+cenOWkza6xtvsT0KGXI03HA==}
     peerDependencies:
       better-sqlite3: ^7.1.1 || ^8.0.0 || ^9.0.0
@@ -9583,7 +9635,7 @@ packages:
       '@opentelemetry/core': 1.18.1(@opentelemetry/api@1.7.0)
       '@opentelemetry/instrumentation': 0.44.0(@opentelemetry/api@1.7.0)
       '@opentelemetry/semantic-conventions': 1.18.1
-      better-sqlite3: 7.6.2
+      better-sqlite3: 9.2.2
     transitivePeerDependencies:
       - supports-color
     dev: false
@@ -9827,7 +9879,6 @@ packages:
       pino: 8.15.0
       pino-std-serializers: 6.2.2
       process-warning: 2.2.0
-    dev: false
 
   /pino-http@8.4.0:
     resolution: {integrity: sha512-9I1eRLxsujQJwLQTrHBU0wDlwnry2HzV2TlDwAsmZ9nT3Y2NQBLrz+DYp73L4i11vl/eudnFT8Eg0Kp62tMwEw==}
@@ -10047,7 +10098,6 @@ packages:
 
   /punycode@1.4.1:
     resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
-    dev: false
 
   /punycode@2.3.0:
     resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
@@ -10962,7 +11012,7 @@ packages:
       yn: 3.1.1
     dev: true
 
-  /ts-node@10.8.2(@swc/core@1.3.42)(@types/node@18.17.8)(typescript@4.9.5):
+  /ts-node@10.8.2(@swc/core@1.3.42)(@types/node@20.10.4)(typescript@5.3.3):
     resolution: {integrity: sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==}
     hasBin: true
     peerDependencies:
@@ -10982,14 +11032,14 @@ packages:
       '@tsconfig/node12': 1.0.11
       '@tsconfig/node14': 1.0.3
       '@tsconfig/node16': 1.0.4
-      '@types/node': 18.17.8
+      '@types/node': 20.10.4
       acorn: 8.10.0
       acorn-walk: 8.2.0
       arg: 4.1.3
       create-require: 1.1.1
       diff: 4.0.2
       make-error: 1.3.6
-      typescript: 4.9.5
+      typescript: 5.3.3
       v8-compile-cache-lib: 3.0.1
       yn: 3.1.1
     dev: true
@@ -11131,9 +11181,9 @@ packages:
     hasBin: true
     dev: true
 
-  /typescript@4.9.5:
-    resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
-    engines: {node: '>=4.2.0'}
+  /typescript@5.3.3:
+    resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
+    engines: {node: '>=14.17'}
     hasBin: true
     dev: true
 
@@ -11158,6 +11208,10 @@ packages:
       which-boxed-primitive: 1.0.2
     dev: true
 
+  /undici-types@5.26.5:
+    resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+    dev: true
+
   /unicode-canonical-property-names-ecmascript@2.0.0:
     resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==}
     engines: {node: '>=4'}