@kensio/yulin 1.21.7 → 1.21.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +22 -2
  2. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +2 -0
  3. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +1 -1
  4. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +2 -0
  5. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +4 -0
  6. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -5
  7. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.d.ts +2 -0
  8. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +2 -0
  9. package/dist/service/lambda/command/event-source-mapping/sim-lambda-event-source-mapping-commands.d.ts +2 -0
  10. package/dist/service/lambda/destination/sim-lambda-destination-targets.d.ts +2 -1
  11. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +0 -4
  12. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +10 -15
  13. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +1 -6
  14. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +9 -27
  15. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.d.ts +19 -0
  16. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.js +27 -0
  17. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.d.ts +1 -1
  18. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.js +3 -1
  19. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.d.ts +13 -0
  20. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.js +27 -0
  21. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.d.ts +15 -0
  22. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.js +26 -0
  23. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.d.ts +1 -0
  24. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.js +7 -1
  25. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.d.ts +17 -0
  26. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.js +12 -0
  27. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.d.ts +15 -0
  28. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.js +28 -0
  29. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.d.ts +19 -0
  30. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.js +23 -0
  31. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.d.ts +3 -0
  32. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.js +19 -0
  33. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.d.ts +15 -0
  34. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.js +38 -0
  35. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.d.ts +41 -0
  36. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.js +17 -0
  37. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.d.ts +21 -0
  38. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.js +39 -0
  39. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.d.ts +7 -37
  40. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.js +22 -62
  41. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.d.ts +4 -39
  42. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.js +12 -64
  43. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -3
  44. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +12 -3
  45. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.d.ts +7 -0
  46. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.js +38 -0
  47. package/dist/service/lambda/event-source/stream/kinesis/sim-kinesis-event-source-streams.js +1 -0
  48. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-reader.js +1 -0
  49. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.d.ts +1 -0
  50. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.js +7 -0
  51. package/dist/service/lambda/event-source/stream/sim-lambda-event-source-streams.d.ts +1 -0
  52. package/dist/service/lambda/index.d.ts +1 -0
  53. package/dist/service/lambda/sim-lambda-commands.js +1 -0
  54. package/dist/service/ses/command/authorize/sim-ses-authorizer.d.ts +9 -0
  55. package/dist/service/ses/command/authorize/sim-ses-authorizer.js +18 -2
  56. package/dist/service/ses/command/send/sim-ses-send-email.js +2 -1
  57. package/docs/README.md +7 -0
  58. package/docs/ai-skill/README.md +6 -1
  59. package/docs/sdk/README.md +15 -0
  60. package/docs/services/acm/README.md +24 -40
  61. package/docs/services/apigateway/README.md +52 -71
  62. package/docs/services/apigatewayv2/README.md +55 -74
  63. package/docs/services/athena/README.md +17 -26
  64. package/docs/services/backup/README.md +29 -39
  65. package/docs/services/bedrock/README.md +38 -52
  66. package/docs/services/cloudformation/README.md +43 -55
  67. package/docs/services/cloudfront/README.md +69 -95
  68. package/docs/services/cloudwatch/README.md +40 -54
  69. package/docs/services/cognito/README.md +30 -45
  70. package/docs/services/dynamodb/README.md +34 -51
  71. package/docs/services/ecr/README.md +36 -77
  72. package/docs/services/ecs/README.md +26 -46
  73. package/docs/services/elbv2/README.md +19 -29
  74. package/docs/services/eventbridge/README.md +14 -18
  75. package/docs/services/firehose/README.md +24 -32
  76. package/docs/services/glue/README.md +41 -78
  77. package/docs/services/iam/README.md +13 -15
  78. package/docs/services/kinesis/README.md +53 -93
  79. package/docs/services/kms/README.md +22 -32
  80. package/docs/services/lambda/README.md +112 -85
  81. package/docs/services/logs/README.md +41 -50
  82. package/docs/services/organizations/README.md +50 -85
  83. package/docs/services/personalize/README.md +28 -44
  84. package/docs/services/rekognition/README.md +26 -38
  85. package/docs/services/route53/README.md +17 -17
  86. package/docs/services/s3/README.md +47 -51
  87. package/docs/services/scheduler/README.md +41 -52
  88. package/docs/services/secretsmanager/README.md +27 -42
  89. package/docs/services/ses/README.md +24 -34
  90. package/docs/services/sns/README.md +18 -26
  91. package/docs/services/sqs/README.md +14 -14
  92. package/docs/services/ssm/README.md +13 -17
  93. package/docs/services/stepfunctions/README.md +18 -20
  94. package/docs/services/sts/README.md +32 -45
  95. package/docs/services/wafv2/README.md +12 -17
  96. package/docs/testing/README.md +228 -0
  97. package/docs/time/README.md +10 -0
  98. package/llms.txt +1 -0
  99. package/package.json +1 -1
@@ -1,17 +1,15 @@
1
1
  # Simulated KMS
2
2
 
3
- Yulin includes a simulated AWS Key Management Service (KMS) for tests and local development.
4
-
5
- Encryption is real. Each simulated key holds AES-256 key material and the operations run through
6
- Node.js's own `crypto`. A ciphertext can only be read with its key, and a decryption with the wrong
7
- encryption context fails.
3
+ Yulin simulates AWS Key Management Service (KMS) in memory. Symmetric keys use AES-256 key material,
4
+ and asymmetric keys use real key pairs. Cryptographic operations run through Node.js `crypto`, so
5
+ the wrong key or encryption context cannot decrypt a ciphertext.
8
6
 
9
7
  KMS-specific types are imported from the `@kensio/yulin/kms` subpath.
10
8
 
11
9
  ## Encrypting and decrypting
12
10
 
13
- Create a key and use it. `Decrypt` needs no `KeyId` for a symmetric key, because the ciphertext
14
- already names the key that produced it.
11
+ Create a key, encrypt a value, then decrypt it. `Decrypt` does not need a `KeyId` for symmetric
12
+ ciphertext because the ciphertext identifies its key.
15
13
 
16
14
  ```typescript sim-kms-encrypt-decrypt
17
15
  /**
@@ -52,8 +50,8 @@ any second `SimAws` instance both reject it.
52
50
 
53
51
  ## Encryption context
54
52
 
55
- An encryption context is non-secret key/value data bound to a ciphertext. Decryption with a
56
- different context fails. That ties a ciphertext to the thing it belongs to.
53
+ An encryption context binds non-secret key/value data to a ciphertext. Decryption requires the same
54
+ context.
57
55
 
58
56
  ```typescript sim-kms-encryption-context
59
57
  /**
@@ -100,9 +98,8 @@ The context is an unordered map. The same pairs written in a different order sti
100
98
 
101
99
  ## Envelope encryption
102
100
 
103
- `Encrypt` takes at most 4096 bytes. That limit is what makes envelope encryption necessary.
104
- `GenerateDataKey` returns a data key twice, once in the clear to encrypt your data with, and once
105
- encrypted under the KMS key to store alongside it.
101
+ `Encrypt` accepts at most 4,096 bytes. For larger values, use `GenerateDataKey`. It returns a
102
+ plaintext data key for encryption and an encrypted copy to store with the data.
106
103
 
107
104
  ```typescript sim-kms-generate-data-key
108
105
  /**
@@ -141,8 +138,8 @@ console.log(recovered.Plaintext?.length); // 32
141
138
 
142
139
  ## Signing and verifying
143
140
 
144
- A key created with `KeyUsage: SIGN_VERIFY` holds a real key pair, and the signatures are real
145
- signatures. A key spec is required, because the default `SYMMETRIC_DEFAULT` spec cannot sign.
141
+ A key with `KeyUsage: SIGN_VERIFY` holds a real key pair. Set a signing key spec because the default
142
+ `SYMMETRIC_DEFAULT` key cannot sign.
146
143
 
147
144
  ```typescript sim-kms-sign-verify
148
145
  /**
@@ -261,9 +258,8 @@ both matching what KMS produces. `GetPublicKey` against a symmetric key is
261
258
 
262
259
  ## Key policies and IAM
263
260
 
264
- Every KMS key has a policy, and it cannot be removed. An IAM policy granting `kms:Decrypt` only
265
- takes effect where the key's own policy admits the caller. How it admits them decides what else is
266
- needed:
261
+ Every key has a key policy. An identity policy granting `kms:Decrypt` works only when the key policy
262
+ also permits the caller:
267
263
 
268
264
  - A statement naming the caller grants access outright. A role with no permissions of its own can
269
265
  still use the key.
@@ -342,16 +338,15 @@ on real KMS.
342
338
 
343
339
  ## AWS managed keys and `kms:ViaService`
344
340
 
345
- An alias beginning `alias/aws/` names an AWS managed key, and the key is created the first time
346
- something references it. Such a key gets the policy real AWS gives it, which differs from the
347
- customer default:
341
+ An alias beginning with `alias/aws/` names an AWS managed key. Yulin creates that key when it is
342
+ first referenced and applies AWS-managed-key policy behavior:
348
343
 
349
344
  - Use of the key is allowed to any principal in the owning account, but only when `kms:ViaService`
350
345
  names the service that owns the key, such as `ssm.us-east-1.amazonaws.com` for `aws/ssm`.
351
- - The account root is allowed to read the key's metadata. That is the whole of what this policy
352
- delegates to IAM.
346
+ - The account root can read the key's metadata.
353
347
 
354
- That is why a role holding `kms:Decrypt` on such a key cannot use it by calling KMS itself.
348
+ A role cannot use an AWS managed key by calling KMS directly, even when its identity policy grants
349
+ `kms:Decrypt`.
355
350
 
356
351
  `kms:ViaService` is set by the service making the call on the caller's behalf. Sim SSM does this for
357
352
  `SecureString` parameters. Code calling simulated KMS directly sets it with the `viaService` request
@@ -417,8 +412,7 @@ and a condition on it stays unmatched.
417
412
 
418
413
  ## Naming a key
419
414
 
420
- Every operation takes its target as a `KeyId`, in any of the four forms real KMS accepts. Those are
421
- a key ID, a key ARN, an alias name such as `alias/app-key`, and an alias ARN.
415
+ `KeyId` accepts a key ID, key ARN, alias name such as `alias/app-key`, or alias ARN.
422
416
 
423
417
  A key ARN or alias ARN naming another account or region resolves to no key at all. Its identifier is
424
418
  never read out and looked up locally. A foreign ARN cannot reach a key that happens to share an
@@ -473,8 +467,8 @@ console.log(managed.KeyMetadata?.KeyManager); // "AWS"
473
467
 
474
468
  A key can be disabled and re-enabled later. A disabled key stays present, and refuses to be used.
475
469
 
476
- Deletion is never immediate. `ScheduleKeyDeletion` sets a recovery window of 7 to 30 days, defaulting
477
- to 30. During that window the key refuses to be used but can still be recovered with
470
+ `ScheduleKeyDeletion` sets a recovery window from 7 to 30 days, defaulting to 30. During that window
471
+ the key cannot be used but can be recovered with
478
472
  `CancelKeyDeletion`. Cancelling leaves the key disabled. Re-enabling it is a separate step.
479
473
 
480
474
  A disabled key fails cryptographic operations with `DisabledException`. A key pending deletion fails
@@ -600,9 +594,7 @@ the function's execution role as the caller. A handler that decrypts a value the
600
594
  allowed to, by both the key policy and the role's identity policy, the same as on real AWS. See
601
595
  [simulated Lambda](https://yulinsim.dev/services/lambda/) for how function code and execution roles work.
602
596
 
603
- ## Available functionality
604
-
605
- Sim KMS currently supports:
597
+ ## Supported operations
606
598
 
607
599
  - `CreateKeyCommand`, for symmetric encryption keys and asymmetric signing keys
608
600
  - `DescribeKeyCommand` and `ListKeysCommand`
@@ -619,8 +611,6 @@ Sim KMS currently supports:
619
611
 
620
612
  ## Limitations
621
613
 
622
- Current documented limitations:
623
-
624
614
  - Only encryption with a symmetric key and signing with an asymmetric key are simulated. Left out
625
615
  are asymmetric encryption (`RSAES_OAEP_SHA_1` and `RSAES_OAEP_SHA_256`), HMAC keys and
626
616
  `GENERATE_VERIFY_MAC`, key agreement and `DeriveSharedSecret`, the `SM2` key spec, and
@@ -1,7 +1,7 @@
1
1
  # Simulated Lambda
2
2
 
3
- Yulin includes a simulated AWS Lambda service for tests and local development. Functions are created
4
- and invoked in-process and in memory, with no containers and no real AWS infrastructure.
3
+ Yulin creates and invokes Lambda functions in process. A function can use an in-process handler,
4
+ code from a zip archive, code stored in simulated S3, or a handler bound to a container image.
5
5
 
6
6
  Handlers run with their execution role as the simulated caller, so AWS calls made inside a handler
7
7
  are authorized by simulated IAM, as on real Lambda. Creating a function and changing its role are
@@ -9,16 +9,14 @@ authorized as well, both against `lambda:` actions and against `iam:PassRole` on
9
9
  the request names. See [passing a Role to a service](https://yulinsim.dev/services/iam/#passing-a-role-to-a-service)
10
10
  in the IAM docs.
11
11
 
12
- Lambda-specific helpers are imported from the `@kensio/yulin/lambda` subpath. Real `LambdaClient`
13
- instances can be routed into sim Lambda with
12
+ Lambda helpers are available from `@kensio/yulin/lambda`. A `LambdaClient` can be routed to Yulin with
14
13
  [SDK interception](https://yulinsim.dev/sdk/ "Simulated AWS SDK interception docs").
15
14
 
16
15
  ## Creating and invoking a function
17
16
 
18
- The quickest way to a working function is to pass a real in-process handler function through the
19
- SDK-shaped `Code.ZipFile` input with `makeLambdaZipFileInput(...)`. The handler is an ordinary
20
- function in your Node.js process. It can be stepped through in a debugger and can close over local
21
- state.
17
+ Use `makeLambdaZipFileInput(...)` to pass an in-process handler through the SDK-shaped `Code.ZipFile`
18
+ input. The handler runs as an ordinary function in the Node.js process. It supports breakpoints and
19
+ access to local state.
22
20
 
23
21
  ```typescript sim-lambda-create-and-invoke
24
22
  /**
@@ -84,18 +82,13 @@ The invoke call itself returns normally.
84
82
 
85
83
  ## Zip-packaged code and the vm runtime
86
84
 
87
- A real in-process handler is the one to reach for first. `makeLambdaZipFileInput(...)` backs a
88
- function created through the SDK with one, and an [executable binding](#executable-bindings) backs
89
- one a template declares. The handler stops on a breakpoint and can close over the test's own state.
90
- Run the packaged code where the test is about the bundle a deployment ships, its imports and its
91
- bundling included. Both paths invoke through simulated Lambda, and simulated IAM authorizes the
92
- handler's own AWS calls under the execution role either way.
85
+ Use an in-process handler for most tests. Use packaged code when the test covers the deployed bundle,
86
+ including its imports. Both forms run through simulated Lambda and make AWS calls as the function's
87
+ execution role.
93
88
 
94
- Real Lambda receives function code as a zip archive. `makeLambdaCodeZip(...)` builds real zip
95
- bytes from a source string (which becomes a single `index.js` module) or from a files map keyed by
96
- archive path (like a bundled deployment package). The archive runs in a Node.js `vm` context with
97
- real cold-start semantics. The module is imported once, on first invocation, and module state stays
98
- warm across invocations.
89
+ `makeLambdaCodeZip(...)` builds zip bytes from a source string or a map of archive paths to file
90
+ contents. A source string becomes `index.js`. Yulin runs the archive in a Node.js `vm`, loads the
91
+ module on the first invocation and preserves module state for later invocations.
99
92
 
100
93
  ```typescript sim-lambda-zip-code-vm-runtime
101
94
  /**
@@ -171,18 +164,15 @@ package is refused at cold start. A handler file ending in `.mjs` is reported as
171
164
  Real Lambda has run ES module packages since nodejs14.x, and `NodejsFunction` in CDK emits one
172
165
  under `format: OutputFormat.ESM`.
173
166
 
174
- There are two ways round that. An [executable binding](#executable-bindings) or
175
- `makeLambdaZipFileInput(...)` backs the function with a real in-process handler. The test's own
176
- module system loads that handler, and its format is whatever the test file's is. An ESM project
177
- needs nothing further. Where the archive itself has to be the deployed artefact, compile a CommonJS
178
- build of the same source and deploy that as the function's code.
167
+ Use an [executable binding](#executable-bindings) or `makeLambdaZipFileInput(...)` for an ESM handler.
168
+ The test's module system loads an in-process handler. To test the archive itself, compile the source
169
+ to CommonJS before creating the zip.
179
170
 
180
171
  `Code.ZipFile` bytes that fail to unzip are rejected at creation with the AWS-like
181
172
  `InvalidParameterValueException: Could not unzip uploaded file`.
182
173
 
183
- The archives are real zip files, and they interoperate with real tooling in both directions. A zip
184
- built by any other tool works as `Code.ZipFile` input, and `makeLambdaCodeZip` output can be
185
- unzipped normally.
174
+ `Code.ZipFile` accepts zip archives produced by other tools. Archives from `makeLambdaCodeZip` can
175
+ also be opened with standard zip tools.
186
176
 
187
177
  ### What a handler prints
188
178
 
@@ -408,9 +398,8 @@ writes none of those.
408
398
 
409
399
  ## Function code from S3
410
400
 
411
- Function code can also be fetched from a zip object stored in sim S3, as SAM and CDK deployments
412
- do on real AWS. The code object is fetched once at creation time, as the creating caller, so
413
- simulated IAM applies to the code object read.
401
+ Function code may reference a zip object in simulated S3. Yulin reads the object once during
402
+ function creation as the caller creating the function, so simulated IAM applies to the S3 read.
414
403
 
415
404
  ```typescript sim-lambda-s3-code
416
405
  /**
@@ -944,10 +933,9 @@ the operation header that says so.
944
933
 
945
934
  ## Invocation types
946
935
 
947
- `InvokeCommand` supports the three AWS invocation types. `RequestResponse` (the default) awaits
948
- the handler and returns its JSON-serialised result as the response payload. `Event` returns `202`
949
- immediately and runs the handler in the background. `DryRun` returns `204` without invoking the
950
- handler at all.
936
+ `InvokeCommand` supports all three invocation types. `RequestResponse` waits for the handler and
937
+ returns its JSON result. `Event` returns 202 and schedules the handler in the background. `DryRun`
938
+ returns 204 without invoking the handler.
951
939
 
952
940
  ```typescript sim-lambda-invocation-types
953
941
  /**
@@ -1007,14 +995,12 @@ covers.
1007
995
 
1008
996
  ## Asynchronous retries and destinations
1009
997
 
1010
- An `Event` invocation whose handler throws is retried twice, as real Lambda retries one. The retries
1011
- wait on the simulated clock, about a minute before the first and two before the second, so a test
1012
- reaches them by advancing time rather than by waiting for it.
998
+ An `Event` invocation retries a failed handler twice by default. Retries use the simulated clock,
999
+ after about one minute and then two minutes. Advance the clock to run them in a test.
1013
1000
 
1014
- `PutFunctionEventInvokeConfigCommand` changes how many retries a function makes and where its
1015
- results go. An invocation that fails its last attempt is sent to the `OnFailure` destination, and
1016
- one whose handler returns is sent to `OnSuccess`. A destination ARN can name a simulated SQS queue,
1017
- SNS topic, EventBridge event bus or Lambda function.
1001
+ `PutFunctionEventInvokeConfigCommand` controls retry count and destinations. Lambda sends a final
1002
+ failure to `OnFailure` and a successful result to `OnSuccess`. Destinations may be SQS, SNS,
1003
+ EventBridge or another Lambda function.
1018
1004
 
1019
1005
  The source function's execution role must allow the operation that writes to the destination:
1020
1006
 
@@ -1154,11 +1140,9 @@ a config of its own, and an invocation of a qualifier with no config of its own
1154
1140
 
1155
1141
  ### Dead-letter targets
1156
1142
 
1157
- `DeadLetterConfig` is the older way to keep a failed asynchronous invocation, and simulated Lambda
1158
- takes it on `CreateFunction` and `UpdateFunctionConfiguration`. Its `TargetArn` names a simulated
1159
- SQS queue or SNS topic, which receives the event as it was invoked rather than the destination
1160
- record around it. The execution role needs `sqs:SendMessage` for a queue or `sns:Publish` for a
1161
- topic. A denied delivery rejects the background task and leaves the target unchanged.
1143
+ `DeadLetterConfig` sends a failed asynchronous event to SQS or SNS. Configure it with
1144
+ `CreateFunction` or `UpdateFunctionConfiguration`. The target receives the original event rather
1145
+ than a destination record. The execution role needs `sqs:SendMessage` or `sns:Publish`.
1162
1146
 
1163
1147
  ```typescript sim-lambda-dead-letter-queue
1164
1148
  /**
@@ -1249,11 +1233,9 @@ A function carrying both a dead-letter target and an `OnFailure` destination sen
1249
1233
 
1250
1234
  ## Versions and aliases
1251
1235
 
1252
- `PublishVersionCommand` copies a function as it stands and numbers the copy. The first is version
1253
- `1`, and each later one counts up. The copy keeps the code, handler, timeout, memory and
1254
- environment it was published with. `CreateAliasCommand` gives one of those versions a name, and
1255
- `UpdateAliasCommand` moves the name to another version, so a deployment can repoint what callers
1256
- invoke.
1236
+ `PublishVersionCommand` creates an immutable numbered copy of the function's code and configuration.
1237
+ Versions start at `1`. `CreateAliasCommand` gives a version a name, and `UpdateAliasCommand` moves
1238
+ that name to another version.
1257
1239
 
1258
1240
  `InvokeCommand` and `GetFunctionCommand` take a `Qualifier` naming a version number or an alias.
1259
1241
  The same qualifier can travel on the `FunctionName` instead, appended to the name (`orders:live`)
@@ -1366,9 +1348,8 @@ ARN. A `FunctionName` carrying a qualifier (`orders:live`) is refused with an
1366
1348
 
1367
1349
  ## Triggering a function from an SQS queue
1368
1350
 
1369
- An event source mapping connects a [simulated queue](https://yulinsim.dev/services/sqs/ "Simulated SQS docs") to a function.
1370
- Messages sent to the queue are delivered to the handler as an SQS event, with the `Records` shape
1371
- real Lambda uses.
1351
+ An event source mapping polls a [simulated queue](https://yulinsim.dev/services/sqs/ "Simulated SQS docs") and invokes the function
1352
+ with an SQS `Records` event.
1372
1353
 
1373
1354
  Polling runs on the simulation's background scheduler. A test awaits
1374
1355
  `simAws.backgroundTasksComplete()` and then asserts, without sleeping.
@@ -1600,10 +1581,9 @@ from.
1600
1581
 
1601
1582
  ### When the handler fails
1602
1583
 
1603
- A handler that returns normally has handled the batch, and the messages are deleted from the queue.
1604
- A handler that throws returns the whole batch. The messages stay on the queue, hidden until their
1605
- visibility timeout lapses, and are delivered again after that. Advancing the simulation's clock is
1606
- what brings them back:
1584
+ A successful handler deletes the batch from the queue. When the handler throws, every message stays
1585
+ in flight until its visibility timeout expires, then becomes available for another delivery. Advance
1586
+ the simulated clock to reach that retry:
1607
1587
 
1608
1588
  ```typescript
1609
1589
  await simAws.clock().advanceBy({ seconds: 31 });
@@ -1618,10 +1598,8 @@ the sender sees is the message coming back.
1618
1598
 
1619
1599
  ### Reporting individual message failures
1620
1600
 
1621
- A queue mapping created with `FunctionResponseTypes: ["ReportBatchItemFailures"]` takes the
1622
- `batchItemFailures` list the handler returns. The message ids named in it go back to the queue, and
1623
- the rest of the batch is deleted. A stream mapping takes the same list and does something else with
1624
- it, under [reporting individual record failures](#reporting-individual-record-failures).
1601
+ A queue mapping with `FunctionResponseTypes: ["ReportBatchItemFailures"]` reads the handler's
1602
+ `batchItemFailures`. Named message IDs return to the queue and the remaining messages are deleted.
1625
1603
 
1626
1604
  ```typescript
1627
1605
  await simAws.lambda().createEventSourceMapping(
@@ -1646,9 +1624,8 @@ or an empty `batchItemFailures` list, has handled the whole batch.
1646
1624
 
1647
1625
  ### Making an SQS event without a queue
1648
1626
 
1649
- A test of the handler on its own, with no queue and no mapping, still has to pass it a whole event.
1650
- `lambdaSqsEventFactory` makes one, and `lambdaSqsEventRecordFactory` makes the records in it. Such a
1651
- test then says what the messages carry and leaves the rest to the factory:
1627
+ Use `lambdaSqsEventFactory` and `lambdaSqsEventRecordFactory` to call an SQS handler without creating
1628
+ a queue or event source mapping:
1652
1629
 
1653
1630
  ```typescript sim-lambda-sqs-event-factory
1654
1631
  /**
@@ -1708,9 +1685,9 @@ the same records whether it carries them or not. The deploy stands and nothing r
1708
1685
 
1709
1686
  ## Triggering a function from a DynamoDB stream
1710
1687
 
1711
- An event source mapping also connects a [simulated table's stream](https://yulinsim.dev/services/dynamodb/#capturing-changes-with-a-stream "Simulated DynamoDB streams docs")
1712
- to a function. Changes to the table are delivered to the handler as a DynamoDB stream event, with
1713
- the `Records` shape real Lambda uses.
1688
+ An event source mapping can also poll a
1689
+ [simulated DynamoDB stream](https://yulinsim.dev/services/dynamodb/#capturing-changes-with-a-stream "Simulated DynamoDB streams docs").
1690
+ Table changes reach the handler as a DynamoDB `Records` event.
1714
1691
 
1715
1692
  `StartingPosition` is required for a stream and is `TRIM_HORIZON` or `LATEST`. `TRIM_HORIZON` reads
1716
1693
  what the stream still holds, so changes made before the mapping existed are delivered too. `LATEST`
@@ -1927,7 +1904,7 @@ with more steps.
1927
1904
  `MaximumRetryAttempts` and `MaximumRecordAgeInSeconds` govern the same failed-batch lifecycle, and a
1928
1905
  stream mapping keeps both. `MaximumRetryAttempts: 0` makes one delivery and no retries, and a
1929
1906
  positive value allows that many retries after the first delivery. `MaximumRecordAgeInSeconds`
1930
- discards a record once the next attempt would fall past that age. Lambda's `-1` means no limit
1907
+ discards expired records before each invocation, including the first poll. Lambda's `-1` means no limit
1931
1908
  (that is what a mapping naming neither reports back).
1932
1909
 
1933
1910
  ```typescript sim-lambda-stream-retry-limits
@@ -2056,11 +2033,62 @@ discarded, and the mapping reads on from behind it.
2056
2033
  10,000 retries, `-1` to 604,800 seconds) is a `ValidationException`. A queue mapping takes neither,
2057
2034
  because a message the handler never takes is left to the queue's own redrive policy.
2058
2035
 
2036
+ ### Sending discarded stream batches to a destination
2037
+
2038
+ DynamoDB Streams and Kinesis mappings accept `DestinationConfig.OnFailure` with a standard SQS
2039
+ queue or SNS topic ARN. Supply it to `CreateEventSourceMapping` or the
2040
+ `AWS::Lambda::EventSourceMapping` resource alongside the retry and record-age limits:
2041
+
2042
+ ```json
2043
+ {
2044
+ "MaximumRetryAttempts": 10,
2045
+ "MaximumRecordAgeInSeconds": 3600,
2046
+ "DestinationConfig": {
2047
+ "OnFailure": {
2048
+ "Destination": "arn:aws:sqs:eu-west-2:111111111111:stream-failures"
2049
+ }
2050
+ }
2051
+ }
2052
+ ```
2053
+
2054
+ CDK's `DynamoEventSource` and `KinesisEventSource` accept `onFailure: new SqsDlq(queue)` or
2055
+ `onFailure: new SnsDlq(topic)`. Their synthesized destination configuration is passed through to
2056
+ the simulated mapping. Create, Get, List and Delete responses preserve that configuration.
2057
+
2058
+ The function's execution role needs `sqs:SendMessage` on the queue or `sns:Publish` on the topic.
2059
+ Delivery goes through the simulated destination service, so its IAM checks and SNS subscriptions
2060
+ apply. An IAM denial or a missing destination rejects `backgroundTasksComplete()` or the clock
2061
+ advance that exhausted the batch. The discarded records have already advanced the checkpoint.
2062
+ Yulin attempts destination delivery once and does not retry a failed send.
2063
+
2064
+ The JSON message follows the AWS
2065
+ [DynamoDB Streams](https://docs.aws.amazon.com/lambda/latest/dg/services-dynamodb-errors.html) and
2066
+ [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/kinesis-on-failure-destination.html)
2067
+ notification formats. Import `SimLambdaStreamFailureRecord` from `@kensio/yulin/lambda` to type it.
2068
+
2069
+ - `version` is `"1.0"` and `timestamp` is the simulated discard time in ISO 8601 format.
2070
+ - `requestContext` contains a generated `requestId`, the mapping's `functionArn`,
2071
+ `approximateInvokeCount`, and either `RetryAttemptsExhausted` or `RecordAgeExceeded` as `condition`.
2072
+ - `responseContext` reports `statusCode: 200` and `executedVersion`. A handler error adds
2073
+ `functionError: "Unhandled"`. A valid partial-batch failure response leaves that field out.
2074
+ Records discarded before any invocation omit `responseContext`.
2075
+ - `DDBStreamBatchInfo` or `KinesisBatchInfo` identifies the stream ARN, shard ID, first and last
2076
+ sequence numbers, first and last arrival times, and batch size. Arrival times are ISO 8601 strings.
2077
+
2078
+ The original record payloads are absent. A successful batch produces no notification. After a
2079
+ partial-batch response, the notification covers the discarded suffix starting at the failed
2080
+ checkpoint. When only an older prefix expires, its notification excludes the younger records.
2081
+ Records already expired on their first poll report zero invocations. Request IDs are generated for
2082
+ the notification and are not correlated with the handler's invocation context.
2083
+
2084
+ S3 destinations, FIFO queues or topics, and `OnSuccess` are refused. SQS source mappings cannot
2085
+ have this destination configuration. The simulator's existing five-retry cap for mappings with
2086
+ neither limit also produces a failure notification when it discards a batch.
2087
+
2059
2088
  ### Reporting individual record failures
2060
2089
 
2061
- A stream mapping created with `FunctionResponseTypes: ["ReportBatchItemFailures"]` takes the
2062
- `batchItemFailures` list the handler returns. For a stream the identifier is the record's
2063
- `SequenceNumber`:
2090
+ A stream mapping with `FunctionResponseTypes: ["ReportBatchItemFailures"]` reads the handler's
2091
+ `batchItemFailures`. Each item identifies a record by `SequenceNumber`:
2064
2092
 
2065
2093
  ```typescript
2066
2094
  await simAws.lambda().createEventSourceMapping(
@@ -2297,8 +2325,7 @@ the three stream actions on the stream ARN and `dynamodb:ListStreams` on every s
2297
2325
  the mapping's execution-role check is looking for.
2298
2326
 
2299
2327
  The properties a non-default `DynamoEventSource` adds are refused by name. Those are
2300
- `FilterCriteria`, `ParallelizationFactor`, `BisectBatchOnFunctionError`, `TumblingWindowInSeconds`
2301
- and `DestinationConfig`.
2328
+ `FilterCriteria`, `ParallelizationFactor`, `BisectBatchOnFunctionError` and `TumblingWindowInSeconds`.
2302
2329
 
2303
2330
  A hand-written template or a SAM application usually gives the function the AWS managed policy
2304
2331
  `AWSLambdaDynamoDBExecutionRole` instead. Simulated IAM has no model for managed policy ARNs, so
@@ -2308,15 +2335,13 @@ Write the grant as an inline policy, as the example above and CDK both do.
2308
2335
 
2309
2336
  ## Triggering a function from a Kinesis stream
2310
2337
 
2311
- An event source mapping also connects a [simulated Kinesis stream](https://yulinsim.dev/services/kinesis/ "Simulated Kinesis Data Streams docs")
2312
- to a function. Records put onto the stream are delivered to the handler as a Kinesis event, with the
2313
- `Records` shape real Lambda uses.
2338
+ An event source mapping can poll a
2339
+ [simulated Kinesis stream](https://yulinsim.dev/services/kinesis/ "Simulated Kinesis Data Streams docs") and invoke the function
2340
+ with a Kinesis `Records` event.
2314
2341
 
2315
- A Kinesis stream has as many shards as it was created with, and every one of them is read. Real
2316
- Lambda runs a processor per shard, and so does this: each shard keeps its own place on the stream,
2317
- delivers its own batches and backs off on its own when a batch fails. One invocation is given
2318
- records from one shard, so a handler that has to see records in order should put them under one
2319
- partition key, which is what puts them on one shard.
2342
+ Yulin reads every shard in a Kinesis stream. Each shard tracks its own iterator, delivers its own
2343
+ batches and backs off independently after a failure. An invocation receives records from one shard.
2344
+ Use one partition key when the handler requires ordered records.
2320
2345
 
2321
2346
  `StartingPosition` is required for a stream. A Kinesis stream takes all three positions.
2322
2347
  `TRIM_HORIZON` reads what the stream still holds, `LATEST` reads only what arrives from the moment
@@ -4180,8 +4205,10 @@ Current documented limitations:
4180
4205
  - Throttling does not drive a retry. A retry follows a handler that threw or ran out of time, and
4181
4206
  the `MaximumEventAgeInSeconds` a config carries is measured from when the invocation was
4182
4207
  accepted.
4183
- - `DestinationConfig` on an event source mapping is left out. It is a different mechanism from the
4184
- asynchronous invocation destinations above.
4208
+ - Stream mappings support standard SQS and SNS `DestinationConfig.OnFailure` destinations.
4209
+ S3 destinations and `OnSuccess` are refused. Destination delivery is attempted once. A delivery
4210
+ failure rejects the background task after the discarded records have advanced the checkpoint.
4211
+ Destination delivery retries and `DestinationDeliveryFailures` metrics are not simulated.
4185
4212
  - A settings change takes effect at once. Real Lambda reports `LastUpdateStatus: "InProgress"` while
4186
4213
  it rolls the change out, and neither that member nor the wait it implies is simulated.
4187
4214
  - A cross-account grant is only half of what admits a call. The caller's own Account has to allow
@@ -4271,7 +4298,7 @@ Current documented limitations:
4271
4298
  it stands.
4272
4299
  - SQS queues, DynamoDB streams and Kinesis streams are the only event sources. Kafka, DocumentDB and
4273
4300
  Kinesis enhanced fan-out consumers are refused outright, and so are `FilterCriteria`,
4274
- `ScalingConfig`, `DestinationConfig`, `BisectBatchOnFunctionError`, `ParallelizationFactor`,
4301
+ `ScalingConfig`, `BisectBatchOnFunctionError`, `ParallelizationFactor`,
4275
4302
  `TumblingWindowInSeconds` and the other mapping inputs this simulation has no behaviour for. An
4276
4303
  `AWS::Lambda::EventSourceMapping` carrying `Tags` is the exception, and deploys with the tags
4277
4304
  dropped and the property recorded.