@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,14 +1,12 @@
1
1
  # Simulated EventBridge Scheduler
2
2
 
3
- Yulin includes a simulated Amazon EventBridge Scheduler for tests and local development. Schedules
4
- are held in memory and every operation is authorized by simulated IAM. Scheduler-specific types are
5
- imported from the `@kensio/yulin/scheduler` subpath.
3
+ Yulin simulates Amazon EventBridge Scheduler in memory. Schedules run when simulated time advances,
4
+ and every management operation is authorized by simulated IAM. Import Scheduler-specific types from
5
+ `@kensio/yulin/scheduler`.
6
6
 
7
- Scheduler is a separate service from [EventBridge](https://yulinsim.dev/services/eventbridge/), not a corner of it. It has its
8
- own SDK client, its own ARN shape, and its own way of reaching a target. A schedule assumes an IAM
9
- execution role, where an EventBridge rule relies on a resource policy admitting a service principal.
10
- A project using Scheduler cannot be tested against simulated EventBridge rules. That is why this
11
- exists separately.
7
+ Scheduler is separate from [EventBridge](https://yulinsim.dev/services/eventbridge/). It uses its own
8
+ SDK client and ARN format. It also assumes an execution role to invoke a target, while EventBridge
9
+ rules use the target's resource policy.
12
10
 
13
11
  ## Creating a schedule
14
12
 
@@ -56,8 +54,7 @@ IAM policy naming a schedule needs the group in it, or it matches no schedule.
56
54
 
57
55
  ## Writing the schedule expression
58
56
 
59
- Three forms, and the same parser as an [EventBridge scheduled
60
- rule](https://yulinsim.dev/services/eventbridge/#rules-that-fire-on-a-schedule) with two differences:
57
+ Scheduler accepts three expression forms:
61
58
 
62
59
  - `at(yyyy-mm-ddThh:mm:ss)` runs once, at that instant. The timezone is a separate setting on the
63
60
  schedule, outside the expression, and a trailing `Z` is refused.
@@ -71,9 +68,7 @@ rule](https://yulinsim.dev/services/eventbridge/#rules-that-fire-on-a-schedule)
71
68
 
72
69
  ## Firing a schedule
73
70
 
74
- A schedule fires on the simulation's clock. Advancing simulated time past a due
75
- instant invokes the target. Leave time alone and the target is never invoked. A nightly job takes no
76
- time at all to test.
71
+ A schedule fires on the simulation's clock. Advance time past a due instant to invoke the target.
77
72
 
78
73
  ```typescript sim-scheduler-firing
79
74
  /**
@@ -163,12 +158,11 @@ own to describe.
163
158
 
164
159
  ### The execution role
165
160
 
166
- This is the part that differs most from an [EventBridge rule](https://yulinsim.dev/services/eventbridge/), and the part that
167
- most often goes wrong in a real account. A rule reaches its target as the `events.amazonaws.com`
168
- service principal, and the target's own resource policy decides. A schedule assumes the `RoleArn` on
169
- its target, and that role's policies decide. No resource policy on the target is involved at all.
161
+ A schedule assumes the target's `RoleArn`, and that role's policies authorize delivery. An
162
+ [EventBridge rule](https://yulinsim.dev/services/eventbridge/) instead invokes as
163
+ `events.amazonaws.com` and depends on the target's resource policy.
170
164
 
171
- Two things therefore have to be right, and they are fixed in different places:
165
+ The execution role needs both:
172
166
 
173
167
  - The role's **trust policy** has to let `scheduler.amazonaws.com` assume it. A role copied from an
174
168
  EventBridge rule trusts `events.amazonaws.com` and fails here.
@@ -176,14 +170,13 @@ Two things therefore have to be right, and they are fixed in different places:
176
170
  `sqs:SendMessage`, `sns:Publish` or `ecs:RunTask`.
177
171
 
178
172
  A trust policy may also carry the condition AWS recommends against the confused deputy problem. The
179
- schedule's group ARN is supplied as `aws:SourceArn`, and the Account the schedule is in as
180
- `aws:SourceAccount`. A role scoped to one schedule group is assumable by schedules in that group and
181
- by nothing else. CDK writes that condition into the execution roles it generates for a schedule
182
- target, so a role taken from a synthesized template works here unchanged.
173
+ schedule's group ARN is supplied as `aws:SourceArn`, and the account is supplied as
174
+ `aws:SourceAccount`. A role scoped to one schedule group is assumable only by schedules in that
175
+ group. CDK writes that condition into the execution roles it generates for a schedule target, so a
176
+ role from a synthesized template works unchanged.
183
177
 
184
- When either is missing the target goes uninvoked and no error is thrown, exactly as on AWS, where the
185
- failure goes to CloudWatch and nowhere the caller can see. `advanceBy(...)` still returns normally. A
186
- test asserting on a failed invocation reads `deliveryFailures`:
178
+ If either permission is missing, `advanceBy(...)` still returns normally and the target is not
179
+ invoked. Read `deliveryFailures` to assert on the failed delivery:
187
180
 
188
181
  ```typescript sim-scheduler-delivery-failures
189
182
  /**
@@ -256,9 +249,8 @@ following delay doubles to 2, 4, 8 seconds and so on. A retry does not run while
256
249
  still. `advanceBy(...)` runs every retry that becomes due in the interval and settles their work
257
250
  before it returns.
258
251
 
259
- Scheduler does not retry a failure that cannot clear by trying the same request. A missing target,
260
- a missing execution role, an execution role that does not trust Scheduler and an IAM denial are
261
- permanent failures. They are abandoned after the initial attempt.
252
+ Scheduler retries only failures that may clear. A missing target, missing execution role, invalid
253
+ trust policy, or IAM denial is permanent and is abandoned after the initial attempt.
262
254
 
263
255
  Set `Target.DeadLetterConfig.Arn` to a standard SQS queue ARN to keep an input that Scheduler abandons.
264
256
  The execution role needs `sqs:SendMessage` on this queue as well as permission to invoke the target.
@@ -267,19 +259,17 @@ shape and include the error, schedule ARN, target ARN, scheduled time and retry
267
259
  `EXHAUSTED_RETRY_CONDITION` is `MaximumRetryAttempts` or `MaximumEventAgeInSeconds` for an exhausted
268
260
  retryable failure. A permanent failure leaves that attribute out.
269
261
 
270
- A successful DLQ send does not add an entry to `deliveryFailures`, since the configured destination
271
- received the input. A missing queue or denied `sqs:SendMessage` is recorded there instead. This keeps
272
- a misconfigured DLQ visible to a test.
262
+ A successful DLQ send leaves `deliveryFailures` empty because the configured destination received the
263
+ input. A missing queue or denied `sqs:SendMessage` is recorded there instead.
273
264
 
274
265
  ### One-time schedules and what happens after
275
266
 
276
- An `at(...)` schedule fires once and then stops. By default it stays in the Account afterwards, which
277
- surprises people who expected it to clean up. It keeps counting against the schedule quota and keeps
278
- turning up in listings. `ActionAfterCompletion: "DELETE"` is what removes it, and after that
279
- `GetSchedule` reports it gone.
267
+ An `at(...)` schedule fires once. It remains in the account unless
268
+ `ActionAfterCompletion: "DELETE"` removes it. A retained schedule continues to appear in listings
269
+ and count against the schedule quota.
280
270
 
281
- A schedule that is disabled when its only instant passes has not completed, since nothing was
282
- invoked. It is still there afterwards whatever `ActionAfterCompletion` says.
271
+ A disabled schedule remains incomplete when its only instant passes. It stays in the account
272
+ regardless of `ActionAfterCompletion`.
283
273
 
284
274
  `State: "DISABLED"` stops a recurring schedule firing while it is off, and an `UpdateSchedule`
285
275
  enabling it picks up from the next due instant. What it missed is never replayed. An update that
@@ -287,9 +277,8 @@ changes the expression reschedules from the new one.
287
277
 
288
278
  ## Running an ECS task on a schedule
289
279
 
290
- A target whose ARN names an ECS cluster runs a [simulated ECS](https://yulinsim.dev/services/ecs/) task, in place of being
291
- invoked with a payload. That is the shape a nightly batch job usually has. A container runs, does
292
- its work and stops.
280
+ A target whose ARN names an ECS cluster runs a [simulated ECS](https://yulinsim.dev/services/ecs/)
281
+ task. Use `EcsParameters` to select the task definition and use `Input` for task overrides.
293
282
 
294
283
  ```typescript sim-scheduler-ecs-target
295
284
  /**
@@ -404,8 +393,8 @@ target with no `Input` runs the task with no overrides.
404
393
 
405
394
  [Simulated ECS](https://yulinsim.dev/services/ecs/) decides which containers actually run. A container
406
395
  with a binding runs its handler, and a container without one is recorded as not simulated.
407
- A target naming a task definition with nothing bound therefore records a task that never started,
408
- and the schedule counts as invoked.
396
+ A target naming a task definition without a bound container records a task that never started, and
397
+ the schedule counts as invoked.
409
398
 
410
399
  ## Updating and deleting
411
400
 
@@ -457,8 +446,8 @@ console.log(described.ScheduleExpression); // "rate(30 minutes)"
457
446
  console.log(described.Description); // undefined, and not by accident
458
447
  ```
459
448
 
460
- `UpdateSchedule` carries the whole of a schedule, and anything an earlier request set and this one
461
- leaves out is gone. That is real behaviour and a common surprise. The schedule has to exist.
449
+ `UpdateSchedule` replaces the full schedule definition. Any optional value omitted from the update
450
+ is removed. The schedule must already exist.
462
451
  Updating one that is absent raises `ResourceNotFoundException`. EventBridge's `PutRule` creates it.
463
452
 
464
453
  `CreateSchedule` for a name that already exists raises `ConflictException`. A deployment running it
@@ -618,10 +607,10 @@ against the `RoleArn` on the target.
618
607
 
619
608
  ## Deploying from a CloudFormation template
620
609
 
621
- `AWS::Scheduler::Schedule` deploys through [simulated CloudFormation](https://yulinsim.dev/services/cloudformation/). A stack
622
- that declares its schedules can be exercised end to end, with no SDK calls of its own. Everything the
623
- Resource carries lines up with `CreateSchedule`, and a target ARN or execution role resolved by
624
- `Fn::GetAtt` from the same template works as it would in a real deployment.
610
+ `AWS::Scheduler::Schedule` deploys through [simulated
611
+ CloudFormation](https://yulinsim.dev/services/cloudformation/). Its properties follow
612
+ `CreateSchedule`, and the target ARN or execution role can use `Fn::GetAtt` references to resources
613
+ in the same template.
625
614
 
626
615
  ```typescript sim-scheduler-cloudformation
627
616
  /**
@@ -786,7 +775,7 @@ anyway. Read the record back from `stack.getResource("<logicalId>")?.ignoredProp
786
775
  Tearing the stack down removes the group. Its schedules go with it, whether or not they are
787
776
  Resources of the same stack.
788
777
 
789
- ## Available functionality
778
+ ## Supported operations
790
779
 
791
780
  - `CreateSchedule`, `GetSchedule`, `UpdateSchedule`, `DeleteSchedule` and `ListSchedules`.
792
781
  - `at(...)`, `rate(...)` and six-field `cron(...)` expressions, fired by advancing the simulation's
@@ -839,7 +828,7 @@ Resources of the same stack.
839
828
  - A target `EventBridgeParameters`, `KinesisParameters`, `SageMakerPipelineParameters` and
840
829
  `SqsParameters` are refused outright, as is `EcsParameters` on a target whose ARN names something
841
830
  other than an ECS cluster. A `DeadLetterConfig` must name a standard SQS queue because simulated
842
- SQS does not support FIFO queues.
831
+ SQS supports only standard queues.
843
832
  - An ECS target's `EcsParameters` takes `TaskDefinitionArn` and `TaskCount`, and takes and ignores
844
833
  `LaunchType`, `PlatformVersion`, `NetworkConfiguration` and `CapacityProviderStrategy`, since
845
834
  there is no placement and no network here for them to apply to. Anything else it can carry, such
@@ -849,5 +838,5 @@ Resources of the same stack.
849
838
  on an ECS target, where every other target type takes any text.
850
839
  - A `TaskCount` above one runs that many simulated tasks, and a bound container handler runs once
851
840
  for each of them, in this process and one after another.
852
- - `KmsKeyArn` is refused, and `ClientToken` is accepted and ignored. Schedule management requests
853
- are not retried, so the token has no request to make idempotent.
841
+ - `KmsKeyArn` is refused, and `ClientToken` is accepted and ignored. Yulin makes each schedule
842
+ management request once, so the token has no retry to make idempotent.
@@ -1,7 +1,7 @@
1
1
  # Simulated Secrets Manager
2
2
 
3
- Yulin includes a simulated AWS Secrets Manager for tests and local development. Secrets are stored
4
- in memory, versioned by staging label, and every operation is authorized by simulated IAM.
3
+ Yulin simulates AWS Secrets Manager in memory. Secrets have encrypted versions and staging labels,
4
+ and simulated IAM authorizes every operation.
5
5
 
6
6
  Secrets Manager-specific types are imported from the `@kensio/yulin/secretsmanager` subpath.
7
7
 
@@ -45,19 +45,14 @@ on read.
45
45
 
46
46
  ## Encryption and KMS permissions
47
47
 
48
- Every version is encrypted through simulated KMS when it is written and decrypted when
49
- `GetSecretValue` reads it. There is no flag for reading a secret without decrypting it. The read
50
- either returns the plaintext or fails.
48
+ Every secret version is encrypted through simulated KMS. `GetSecretValue` decrypts the version and
49
+ either returns its plaintext or fails.
51
50
 
52
- A secret naming no `KmsKeyId` uses the `aws/secretsmanager` AWS managed key, which asks the caller
53
- for no KMS permission at all. Secrets Manager supplies `kms:ViaService`, and that key's policy allows
54
- the account's principals to use it through Secrets Manager. A Lambda role granted only
55
- `secretsmanager:GetSecretValue` therefore reads the secret, as it does on real AWS.
51
+ A secret without `KmsKeyId` uses the `aws/secretsmanager` AWS managed key. Its policy permits use
52
+ through Secrets Manager, so callers do not need a separate KMS permission.
56
53
 
57
- Pass `KmsKeyId` to encrypt under a customer managed key instead, and the caller's own permissions on
58
- that key start to matter. Secrets Manager uses envelope encryption, asking KMS for a data key per
59
- version. A write needs `kms:GenerateDataKey` and a read needs `kms:Decrypt`. A role granted the
60
- secret but not the key fails here, ahead of a deployment.
54
+ Pass `KmsKeyId` to use a customer managed key. Writing a version requires `kms:GenerateDataKey`, and
55
+ reading it requires `kms:Decrypt`, in addition to the relevant Secrets Manager permission.
61
56
 
62
57
  ```typescript sim-secrets-manager-customer-key
63
58
  /**
@@ -141,10 +136,9 @@ they were made with and stay readable, as they do on real AWS.
141
136
 
142
137
  ## Secret ARNs and IAM policies
143
138
 
144
- Real Secrets Manager appends a hyphen and six random characters to the secret name in its ARN. A
145
- secret named `db-creds` gets an ARN ending `:secret:db-creds-AbCdEf`, and sim Secrets Manager does
146
- the same. A policy naming the bare ARN therefore matches nothing, and a policy has to end in
147
- `-??????` or a wildcard.
139
+ Secret ARNs end with a hyphen and six random characters. A secret named `db-creds`, for example,
140
+ gets an ARN ending in `:secret:db-creds-AbCdEf`. An IAM resource pattern for the secret must include
141
+ that suffix, such as `-??????` or `-*`.
148
142
 
149
143
  ```typescript sim-secrets-manager-iam-policy
150
144
  /**
@@ -214,17 +208,16 @@ nothing, here as there.
214
208
 
215
209
  ## Naming a secret
216
210
 
217
- Every operation takes its target as a `SecretId`, in any of the three forms real Secrets Manager
218
- accepts. Those are the friendly name, the full ARN including the suffix, and the partial ARN without
219
- it.
211
+ `SecretId` accepts the friendly name, the full ARN with its random suffix, or the partial ARN without
212
+ the suffix.
220
213
 
221
214
  An ARN naming another account or region resolves to no secret at all. Its name is never read out and
222
215
  looked up locally, and a foreign ARN cannot reach a secret that happens to share a name.
223
216
 
224
217
  ## Versions and staging labels
225
218
 
226
- Every write creates a version, leaving the earlier ones in place. `AWSCURRENT` names the version a
227
- plain read returns, and writing a new current version demotes the previous one to `AWSPREVIOUS`.
219
+ Every write creates a version. `AWSCURRENT` marks the version returned by a plain read. Writing a new
220
+ current version moves `AWSPREVIOUS` to the former current version.
228
221
 
229
222
  ```typescript sim-secrets-manager-staging-labels
230
223
  /**
@@ -273,12 +266,9 @@ label. A version that has lost every label is on its way out of existence, and i
273
266
 
274
267
  ## Deletion and the recovery window
275
268
 
276
- `DeleteSecret` schedules deletion for later. The recovery window is 7 to 30 days, defaulting to 30.
277
- During that window the secret is still there. It can be described and restored, it refuses to be
278
- read or written, and it still holds its name.
279
-
280
- Holding the name is what a redeployed stack hits. Advancing the simulated clock past the window frees
281
- it.
269
+ `DeleteSecret` schedules deletion after a recovery window of 7 to 30 days, defaulting to 30. During
270
+ that window the secret can be described or restored, but it cannot be read or changed. Its name also
271
+ remains reserved. Advance simulated time past the window to complete deletion.
282
272
 
283
273
  ```typescript sim-secrets-manager-deletion
284
274
  /**
@@ -435,14 +425,14 @@ console.log(credentials.username); // "app"
435
425
  console.log(credentials.password?.length); // 24
436
426
  ```
437
427
 
438
- Generated passwords are random. A test reads the value back out of the simulation the way a deployed
439
- application does.
428
+ Generated passwords are random. Read the deployed value through Secrets Manager instead of asserting
429
+ on an exact password.
440
430
 
441
431
  ## Reading a secret with a dynamic reference
442
432
 
443
- A template reads a secret that already exists through a `{{resolve:secretsmanager:...}}` dynamic
444
- reference. The reference is replaced with the secret's value as the resource holding it is created.
445
- CDK emits one from `SecretValue.secretsManager`.
433
+ A `{{resolve:secretsmanager:...}}` dynamic reference reads an existing secret while CloudFormation
434
+ creates the resource containing the reference. CDK emits this form for
435
+ `SecretValue.secretsManager`.
446
436
 
447
437
  The whole form is
448
438
  `{{resolve:secretsmanager:secret-id:secret-string:json-key:version-stage:version-id}}`. Only the
@@ -554,11 +544,10 @@ another resource of the same stack creates is only there in time when the templa
554
544
  Resource properties are reported as they resolved, including this one. Real CloudFormation keeps a
555
545
  resolved secret out of its own logs and events, and sim CloudFormation has no such protection.
556
546
 
557
- ### A reference the simulation cannot answer
547
+ ### Unresolved references
558
548
 
559
- Simulated CloudFormation deploys what it can. A reference naming a secret that was never created
560
- resolves to `dummy-value-for-<secret-id>`, and the stack carries on deploying. A template reading a
561
- secret a test does not care about is still worth deploying for everything else in it.
549
+ If Yulin cannot resolve a reference, it substitutes `dummy-value-for-<secret-id>` and continues the
550
+ deployment.
562
551
 
563
552
  The substitution is recorded on
564
553
  [`stack.ignoredProperties`](https://yulinsim.dev/services/cloudformation/#properties-a-resource-was-created-without),
@@ -596,9 +585,7 @@ The same applies to `SimSdk` interception. Intercepting `SecretsManagerClient` r
596
585
  code into the simulation, served in process. See
597
586
  [AWS SDK interception](https://yulinsim.dev/sdk/ "Simulated AWS SDK docs").
598
587
 
599
- ## Available functionality
600
-
601
- Sim Secrets Manager currently supports:
588
+ ## Supported operations
602
589
 
603
590
  - `CreateSecretCommand`, holding either a string or binary
604
591
  - `GetSecretValueCommand`, by staging label or by version id
@@ -619,8 +606,6 @@ Sim Secrets Manager currently supports:
619
606
 
620
607
  ## Limitations
621
608
 
622
- Current documented limitations:
623
-
624
609
  - A `KmsKeyId` is checked when a version is written under it, not when it is set on its own. An
625
610
  `UpdateSecret` changing only the key accepts a key that is absent, and the next write of a value
626
611
  fails.
@@ -1,20 +1,14 @@
1
1
  # Simulated SES
2
2
 
3
- Yulin includes a simulated Amazon SES for tests and local development, through the SES v2 API. It
4
- holds email identities, applies the sandbox rules, and keeps a record of every message it would have
5
- sent. A test can assert that signing someone up produced a welcome email addressed to them, without
6
- an AWS account and without a mailbox to read.
7
-
8
- There is no delivery to simulate. A message SES accepts leaves AWS for a mail system. The whole of
9
- the observable AWS behaviour is whether SES would have accepted the message and what it would have
10
- sent. That is what makes this service small and what makes it useful.
3
+ Yulin simulates the Amazon SES v2 API in memory. It stores email identities, applies sandbox and
4
+ suppression rules, renders templates, and records accepted messages. It does not deliver email.
11
5
 
12
6
  SES specific types are imported from the `@kensio/yulin/ses` subpath.
13
7
 
14
8
  ## Asserting on a message that was sent
15
9
 
16
- `sentEmails()` hands over the record. Each message carries who it was from, the three recipient
17
- lists, the subject, the body, its attachments and the message id SES answered with.
10
+ Use `sentEmails()` to inspect accepted messages. Each record contains the sender, To/Cc/Bcc lists,
11
+ subject, body, attachments, and message ID.
18
12
 
19
13
  ```typescript sim-ses-send-and-assert
20
14
  /**
@@ -115,9 +109,8 @@ console.log(
115
109
 
116
110
  ## Verifying identities
117
111
 
118
- Real SES verifies an email address by emailing it a link and a domain by looking for DNS records.
119
- Neither can happen inside a test process, so verification here is the simulator's own operation
120
- instead of an API call. `verifyIdentity` performs it, creating the identity where one is absent.
112
+ SES normally verifies an address by email and a domain through DNS. In tests, call `verifyIdentity`
113
+ instead. It creates the identity if necessary and marks it verified.
121
114
 
122
115
  Everything else about identities is the ordinary SES API. `CreateEmailIdentity` starts one, and it
123
116
  starts unverified, exactly as a real one does:
@@ -631,13 +624,10 @@ one answer whoever asked.
631
624
 
632
625
  ## The sandbox
633
626
 
634
- An account starts in the SES sandbox, where **both** the sender and every recipient have to be
635
- verified. That is the state most tests should be written against. It is the configuration that
636
- refuses to mail an address nobody verified, and catching that refusal in a test is much better than
637
- catching it in an account.
627
+ An account starts in the SES sandbox. Both the sender and every recipient must be verified. Outside
628
+ the sandbox, only the sender must be verified.
638
629
 
639
- Outside the sandbox only the sender is checked. `PutAccountDetails` with `ProductionAccessEnabled`
640
- is how an account gets there:
630
+ Call `PutAccountDetails` with `ProductionAccessEnabled` to leave the sandbox:
641
631
 
642
632
  ```typescript sim-ses-sandbox
643
633
  /**
@@ -696,17 +686,12 @@ caller finds out everything it has to verify from one failure:
696
686
  Email address is not verified. The following identities failed the check in region US-EAST-1: someone@example.org
697
687
  ```
698
688
 
699
- Real SES treats `ProductionAccessEnabled` as a request that a human at AWS then reviews, and an
700
- account stays in the sandbox until that review lands. Granting it immediately is a deliberate
701
- divergence. The alternative is a simulator no test can get out of the sandbox in, and waiting for a
702
- review is beyond what a test can assert on anyway.
689
+ Unlike AWS, Yulin grants production access immediately instead of waiting for a manual review.
703
690
 
704
691
  ## The suppression list
705
692
 
706
- Real SES holds an account-level suppression list and fills it from hard bounces and complaints.
707
- Tests supply that feedback explicitly with `recordFeedback`. Suppression commands manage the same
708
- list. The support tool that lists suppressed addresses, the form that removes one and the script
709
- that seeds the list all have somewhere to run.
693
+ SES maintains an account suppression list for hard bounces and complaints. Tests add feedback with
694
+ `recordFeedback`, and the suppression commands read and change the same list.
710
695
 
711
696
  `PutSuppressedDestination`, `GetSuppressedDestination`, `ListSuppressedDestinations` and
712
697
  `DeleteSuppressedDestination` manage it.
@@ -870,8 +855,7 @@ recorded.
870
855
 
871
856
  ## Messages on the console
872
857
 
873
- `sentEmails()` is test code. A dev server has the same messages going past and nothing to read them
874
- with, so `serveSimAws` prints a summary of each one as SES accepts it:
858
+ For local development, `serveSimAws` prints a summary whenever SES accepts a message:
875
859
 
876
860
  ```
877
861
  sim SES: hello@example.com to alice@example.com, bcc audit@example.com
@@ -899,13 +883,12 @@ pool kept. Both services recorded it, and each block says what that service hold
899
883
 
900
884
  ## Permissions
901
885
 
902
- Every command authorizes through simulated IAM. A send authorizes against the identity being sent
903
- **from**, and recipients never enter into it. That is worth knowing when a policy looks like it
904
- should cover a send and fails to.
886
+ Every command uses simulated IAM. A send authorizes against the sender identity, not the recipient
887
+ addresses.
905
888
 
906
889
  ```typescript sim-ses-permissions
907
890
  /**
908
- * A Role that may only send from one domain.
891
+ * A Role that may only send from one address at a verified domain.
909
892
  */
910
893
 
911
894
  import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
@@ -945,6 +928,9 @@ await simAws.iam().putRolePolicy(
945
928
  Effect: "Allow",
946
929
  Action: "ses:SendEmail",
947
930
  Resource: "arn:aws:ses:us-east-1:111111111111:identity/example.com",
931
+ Condition: {
932
+ StringEquals: { "ses:FromAddress": "hello@example.com" },
933
+ },
948
934
  },
949
935
  ],
950
936
  }),
@@ -953,7 +939,7 @@ await simAws.iam().putRolePolicy(
953
939
 
954
940
  await ses.sendEmail(
955
941
  new SendEmailCommand({
956
- FromEmailAddress: "anything@example.com",
942
+ FromEmailAddress: "hello@example.com",
957
943
  Destination: { ToAddresses: ["someone@example.com"] },
958
944
  Content: {
959
945
  Simple: {
@@ -978,6 +964,10 @@ The more specific identity wins when both exist. A policy naming `identity/examp
978
964
  send from any address at the domain, unless that address is an identity in its own right, in which
979
965
  case the send authorizes against `identity/hello@example.com` instead.
980
966
 
967
+ `ses:FromAddress` carries the bare `FromEmailAddress`. A policy can use it to allow one address at a
968
+ verified domain. A display name does not change the value. For example, `Welcome team
969
+ <hello@example.com>` supplies `hello@example.com` to IAM.
970
+
981
971
  `ses:ListEmailIdentities`, `ses:GetAccount` and `ses:PutAccountDetails` have no resource type at all
982
972
  on real SES, and only a policy written against `*` allows them. A policy scoped to identity ARNs
983
973
  allows none of the three. Not even one written against `identity/*`, the intuitive reading and the
@@ -1,14 +1,11 @@
1
1
  # Simulated SNS
2
2
 
3
- Yulin includes a simulated Amazon SNS for tests and local development. Topics are held in memory and
4
- every operation is authorized by simulated IAM.
3
+ Yulin simulates Amazon SNS standard topics for tests and local development. A published message can
4
+ reach simulated SQS queues, invoke simulated Lambda functions or create SMS records that tests can
5
+ inspect. Direct SMS publishes are recorded in the same way.
5
6
 
6
- Standard topics only. SNS-specific types are imported from the `@kensio/yulin/sns` subpath.
7
-
8
- A message published to a topic is delivered to every queue subscribed to it, invokes every Lambda
9
- function subscribed to it, and is recorded as an SMS for every phone number subscribed to it. Only
10
- those three protocols are simulated. A message published straight to a phone number is recorded
11
- as an SMS a test can assert on.
7
+ Topics are stored in memory, and simulated IAM authorizes every operation. FIFO topics and other
8
+ subscription protocols are not simulated. Import SNS-specific types from `@kensio/yulin/sns`.
12
9
 
13
10
  ## Creating a topic and publishing to it
14
11
 
@@ -103,11 +100,10 @@ console.log(read.Attributes?.["SubscriptionsConfirmed"]); // "0"
103
100
  reports it. The three subscription counts are reported as zero, the counts a topic with no
104
101
  subscriptions has.
105
102
 
106
- An attribute real SNS has and this simulation gives no behaviour to is refused by name rather than
107
- taken and ignored. That covers `FifoTopic`, `KmsMasterKeyId`, `SignatureVersion`, `TracingConfig`,
108
- `ArchivePolicy`, `DeliveryPolicy`, `ContentBasedDeduplication` and the delivery status logging
109
- attributes such as `SQSSuccessFeedbackRoleArn`. A topic that appeared to accept `KmsMasterKeyId`
110
- would look encrypted to the request that set it and be plain to everything else.
103
+ Unsupported topic attributes are rejected instead of being stored without effect. These include
104
+ `FifoTopic`, `KmsMasterKeyId`, `SignatureVersion`, `TracingConfig`, `ArchivePolicy`, `DeliveryPolicy`,
105
+ `ContentBasedDeduplication` and delivery status logging attributes such as
106
+ `SQSSuccessFeedbackRoleArn`.
111
107
 
112
108
  ## Publishing
113
109
 
@@ -148,12 +144,11 @@ const published = await sns.publish(
148
144
  console.log(published.MessageId !== undefined); // true
149
145
  ```
150
146
 
151
- The name and data type rules are the real ones. A data type is `String`, `String.Array`, `Number` or
152
- `Binary`, and each takes a custom label after a dot, so `Number.int` is a number as far as the rules
153
- go. A reserved `AWS.` or `Amazon.` prefix on a name, a data type built on none of the four, or a
154
- value that disagrees with its data type is refused. A test finds any of those without going near AWS. The two reserved names real
155
- SNS defines for SMS, `AWS.SNS.SMS.SenderID` and `AWS.SNS.SMS.SMSType`, are the exception.
156
- [Sending an SMS](#sending-an-sms) covers those.
147
+ Message attributes use the AWS name and type rules. A type starts with `String`, `String.Array`,
148
+ `Number` or `Binary` and may add a custom label after a dot, such as `Number.int`. SNS rejects
149
+ reserved `AWS.` and `Amazon.` name prefixes, unknown base types and values that do not match their
150
+ type. The SMS attributes `AWS.SNS.SMS.SenderID` and `AWS.SNS.SMS.SMSType` are exceptions. See
151
+ [Sending an SMS](#sending-an-sms).
157
152
 
158
153
  A `Subject` is UTF-8 text with no line breaks or control characters, of fewer than 100 characters.
159
154
  That is the contract real SNS states. A subject of exactly 100 characters is already too long. A
@@ -164,9 +159,8 @@ publish with no `Message`, or with one over the size limit, is refused with
164
159
  the rest of the batch goes through, as real SNS reports it. An empty batch, more than ten entries, a
165
160
  malformed entry id or two entries sharing an id fail the whole request.
166
161
 
167
- The size limit is the one thing a batch is held to as a whole. Ten entries each just inside it are
168
- one batch far outside it, and a single entry over it fails the whole batch with
169
- `BatchRequestTooLongException`. The response singles out no entry.
162
+ The size limit applies to the whole batch. A batch over the limit fails with
163
+ `BatchRequestTooLongException`, without identifying one entry as the cause.
170
164
 
171
165
  ```typescript sim-sns-publish-batch
172
166
  /**
@@ -1762,9 +1756,9 @@ synthesises an `AWS::SNS::Subscription` alongside the `AWS::SQS::QueuePolicy` th
1762
1756
  delivery, and both deploy. `new subscriptions.LambdaSubscription(fn)` does the same with the
1763
1757
  `AWS::Lambda::Permission` beside it.
1764
1758
 
1765
- ## Available functionality
1759
+ ## Supported operations
1766
1760
 
1767
- Sim SNS currently supports:
1761
+ Simulated SNS supports:
1768
1762
 
1769
1763
  - `CreateTopicCommand`, idempotent for a name already taken, and `DeleteTopicCommand`
1770
1764
  - `ListTopicsCommand`, paged at a hundred topics with a `NextToken`
@@ -1807,8 +1801,6 @@ Sim SNS currently supports:
1807
1801
 
1808
1802
  ## Limitations
1809
1803
 
1810
- Current documented limitations:
1811
-
1812
1804
  - Only the `sqs`, `lambda` and `sms` subscription protocols are simulated. A queue, a function and a
1813
1805
  phone number are the only things a topic can deliver to. `http`, `https`, `email`, `email-json`,
1814
1806
  `application` and `firehose` are refused at `Subscribe` time.
@@ -1,9 +1,11 @@
1
1
  # Simulated SQS
2
2
 
3
- Yulin includes a simulated Amazon SQS for tests and local development. Messages are held in memory,
4
- hidden and released on the simulation's own clock, and every operation is authorized by simulated IAM.
3
+ Yulin simulates Amazon SQS standard queues for tests and local development. You can create queues,
4
+ send and receive messages, test visibility timeouts and redrive messages to dead-letter queues.
5
+ Messages are stored in memory, time-based behavior uses the simulation's clock, and simulated IAM
6
+ authorizes every operation.
5
7
 
6
- Standard queues only. SQS-specific types are imported from the `@kensio/yulin/sqs` subpath.
8
+ FIFO queues are not simulated. Import SQS-specific types from `@kensio/yulin/sqs`.
7
9
 
8
10
  ## Creating a queue and sending a message
9
11
 
@@ -57,10 +59,9 @@ differ. A request naming no attributes always matches.
57
59
 
58
60
  ## Visibility timeouts
59
61
 
60
- A received message is hidden from other consumers for the queue's visibility timeout, 30 seconds by
61
- default. The message records the instant it is hidden until. It becomes receivable again once
62
- simulated time reaches that instant. Advancing the clock is all a test needs to watch an undeleted
63
- message come back.
62
+ A received message is hidden from other consumers for the queue's visibility timeout, which is 30
63
+ seconds by default. If the consumer does not delete it, the message becomes available again when the
64
+ simulated clock reaches the end of that timeout.
64
65
 
65
66
  ```typescript sim-sqs-visibility-timeout
66
67
  /**
@@ -127,8 +128,8 @@ Every receive issues a fresh receipt handle, and a delete has to use the handle
127
128
  receive of that message. A handle from an earlier receive is accepted and deletes nothing. Real SQS
128
129
  accepts one too, and promises only that the message might not be deleted.
129
130
 
130
- That is the failure a consumer slower than its visibility timeout hits. Its message went back on the
131
- queue, someone else took it, and its own delete quietly does nothing.
131
+ This can happen when a consumer runs past the visibility timeout and another consumer receives the
132
+ same message. The first consumer's later delete succeeds without deleting the message.
132
133
 
133
134
  ```typescript sim-sqs-stale-receipt-handle
134
135
  /**
@@ -187,10 +188,9 @@ still the most recent one, so deleting with it works. A handle the queue never i
187
188
 
188
189
  ## Dead-letter queues
189
190
 
190
- A `RedrivePolicy` says where a message goes once a consumer has had enough attempts at it. Once a
191
- message has been received `maxReceiveCount` times without being deleted, the next lapse of its
192
- visibility timeout moves it to the queue named by `deadLetterTargetArn`. Advancing the clock drives
193
- the move, as it drives the timeout itself.
191
+ A `RedrivePolicy` sends repeatedly received messages to a dead-letter queue. After a message reaches
192
+ `maxReceiveCount` without being deleted, the next visibility timeout moves it to the queue named by
193
+ `deadLetterTargetArn`. Advance the simulated clock to trigger the timeout and move.
194
194
 
195
195
  ```typescript sim-sqs-dead-letter-queue
196
196
  /**
@@ -1137,7 +1137,7 @@ that deploys here, with the queue URL reaching the function through its environm
1137
1137
  policy naming the queue by the ARN `Fn::GetAtt` gives. A grant to a service principal synthesises an
1138
1138
  `AWS::SQS::QueuePolicy` alongside it, which deploys too.
1139
1139
 
1140
- ## Available functionality
1140
+ ## Supported operations
1141
1141
 
1142
1142
  Sim SQS currently supports:
1143
1143